c# JSON Directly Nested Arrays - c#

I'm hitting a RESTful api and trying to process the returned data. The data itself consists of json arrays within arrays.
{
"category1": [
[
"http://url1",
"URL 1 Title"
],
[
"http://url2",
"URL 2 Title"
]
],
"category2": [
[
"http://url3",
"URL 3 Title"
]
],
"category3": [
[
"http://url4",
"URL 4 Title"
]
]
}
I've created a class that maps to the content above, but I have no idea of how to parse the result and extract the individual URL and URL Titles.
I can see how I might do it if these were objects, but no idea on how to access directly nested arrays.

Try this
class Output
{
public string[][] category1 { get; set; }
public string[][] category2 { get; set; }
public string[][] category3 { get; set; }
}
class OutputCategory
{
public string uri { get; set; }
public string label { get; set; }
}
I have modified your code in the main() method to the following one.
string samplejson =
#"{'category1':[['http://url1','URL 1 Title'],['http://url2','URL 2 Title']],'category2':[['http://url3','URL 3 Title']],'category3':[['http://url4','URL 4 Title']]}";
//deserialised to my class object
var result = JsonConvert.DeserializeObject<Output>(samplejson);
//create new output object
Output outCat = new Output();
//I now want to assign the appropriate values to my new output object
Console.WriteLine(result.category2.Length);
Console.WriteLine("URL: " + result.category1[0][0]);
Console.WriteLine("Title: " + result.category1[0][1]);
Make sure you check the length of the array and then proceed with your result.

I am using this in my codes, after you have YourModel class created then you can use the bellow approach
JsonConvert.DeserializeObject<YourModel>(content,
new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});

You want to have jagged arrays:
public class Model
{
public string[][] category1 { get; set; }
public string[][] category2 { get; set; }
public string[][] category3 { get; set; }
}
And then:
var model = JsonConvert.DeserializeObject<Model>(json);
foreach (var element in model.category1)
{
var url = element[0];
var title = element[1];
}

Related

How to access multiple groups of nested JSON elements in C#?

I have a JSON being received from a public API that follows the structure below.
[
{
"ID": "12345",
"company": [
{
"contract_ID": "abc5678",
"company": [
{
"company_name": "HelloWorld",
"company_logo": "HW",
"invested": "2000"
}
]
},
{
"contract_ID": "67891",
"company": [
{
"company_name": "GoodBye",
"company_logo": "GB",
"invested": "500"
}
]
},
{
"contract_ID": "32658",
"company": [
{
"company_name": "YesNo",
"company_logo": "YN",
"invested": "1500"
}
]
}
]
}
]
I've tried several different methods of parsing, whether it be JTokens/JArrays or various classes. Something like the following allows me to access the first group of values (company_name, company_logo, invested), but I cannot iterate through to find the other two.
//receiving the json data
var responseString = await response.Content.ReadAsStringAsync();
var fullJSON = JsonConvert.DeserializeObject(responseString);
Debug.Log(fullJSON);
//trying to parse it down to just the data I need
JToken token = JToken.Parse("{\"root\":" + responseString + "}");
Debug.Log(token);
JArray assets = (JArray)token.SelectToken("root[0].assets");
Debug.Log(assets);
JToken dig = JToken.Parse("{\"root\":" + assets + "}");
Debug.Log(dig);
JArray assetsNested = (JArray)dig.SelectToken("root[0].assets");
Debug.Log(assetsNested);
My goal is to extract the contract_ID and then the associated company_name, company_logo, and invested items. For example, abc5678, HelloWorld, HW, and 2000 would be one of the three datasets needed.
The easiest way to deserialize this properly and keep your code maintainable is to use concrete classes. For example:
public sealed class Company
{
[JsonProperty("contract_ID")]
public string ContractID { get; set; }
[JsonProperty("company")]
public List<CompanyDefinition> CompanyDefinitions { get; set; }
}
public sealed class CompanyDefinition
{
[JsonProperty("company_name")]
public string CompanyName { get; set; }
[JsonProperty("company_logo")]
public string CompanyLogo { get; set; }
[JsonProperty("invested")]
public string Invested { get; set; }
}
public sealed class RootCompany
{
[JsonProperty("ID")]
public string ID { get; set; }
[JsonProperty("company")]
public List<Company> Company { get; set; }
}
Then, you simply deserialize. For example, if you are pulling from a file you could do this:
using(var sr = new StreamReader(#"c:\path\to\json.json"))
using(var jtr = new JsonTextReader(sr))
{
var result = new JsonSerializer().Deserialize<RootCompany[]>(jtr);
foreach(var r in result)
{
Console.WriteLine($"Company ID: {r.ID}");
foreach(var c in r.Company)
{
Console.WriteLine($"ContractID: {c.ContractID}");
foreach(var d in c.CompanyDefinitions)
{
Console.WriteLine($"Name: {d.CompanyName}");
Console.WriteLine($"Invested: {d.Invested}");
Console.WriteLine($"Company Logo: {d.CompanyLogo}");
}
}
}
}
When something changes with your models, you won't have to dig through lines upon lines of hard-to-read token selection code. You just update your models.

Compare JSON array and JSON object: Cannot convert Array to String error

I am trying to compare json value and based on that i want to update the existing value,for example, currently we have "value" : [r0] in json, i want to compare and if value : [r0] ,then update it to [r0,r1] but iam hiting error that it cannot compare and there is a cast issue, could someone suggest what could be done
public void updateJsonParameter(string file)
{
try
{
var list = new List<string> { "joe", "test" };
JArray array = new JArray(list);
var jobject = JObject.Parse(file);
var ringvalue = (string)jobject["properties"]["parameters"]["ringValue"]["value"]; // unable to case here and compare
jobject["properties"]["parameters"]["ringValue"]["value"] = array; // able to update value but i want to update after comparing the existing values
var result = JsonConvert.SerializeObject(jobject);
}
following is the json format
{
"properties": {
"displayName": "jayatestdefid",
"description": "test assignment through API",
"metadata": {
"assignedBy": "xyz#gmail.com"
},
"policyDefinitionId": "/providers/Microsoft.Management/managementgroups/MGTest/providers/Microsoft.Authorization/policyDefinitions/test",
"parameters": {
"ringValue": {
"value": ["r0"]
}
},
"enforcementMode": "DoNotEnforce",
}
}
jobject.properties.parameters.ringValue.value is an array ["r0"] with one element "r0". If you want to check if it's an array with one element and that element is "r0", do exactly that:
var ringvalue = jobject["properties"]["parameters"]["ringValue"]["value"];
if(ringvalue.length == 1 && ringvalue[0] == "r0")
jobject["properties"]["parameters"]["ringValue"]["value"] = array;
You could compare the ringvalue (which is an JArray) using JArray.DeepEquals and then replace if the comparison returns true. For example,
var list = new List<string> { "joe", "test" };
JArray array = new JArray(list);
JArray valueToCompare = new JArray(new[]{"r0"});
var ringvalue = (JArray)jobject["properties"]["parameters"]["ringValue"]["value"];
if(JArray.DeepEquals(ringvalue,valueToCompare))
{
jobject["properties"]["parameters"]["ringValue"]["value"] = array;
}
First, as Klaycon said in his answer, it's worth noting that your "value" is not a single string. In json, whenever you see [ and ] then you have a collection, or an array, or a list.
When I work with json strings, I always like to be able to convert them into a strongly typed object. There is a very handy online tool I use all the time: http://json2csharp.com/
I took your json string that you provided and pasted it into that website. Here is that your object(s) look like when converted into c# classes:
public class RootObject // You can name this whatever you want
{
public Properties properties { get; set; }
}
public class Metadata
{
public string assignedBy { get; set; }
}
public class RingValue
{
public List<string> value { get; set; }
}
public class Parameters
{
public RingValue ringValue { get; set; }
}
public class Properties
{
public string displayName { get; set; }
public string description { get; set; }
public Metadata metadata { get; set; }
public string policyDefinitionId { get; set; }
public Parameters parameters { get; set; }
public string enforcementMode { get; set; }
}
Now, we can easily do the logic you need as follows:
// This is your json string, escaped and turned into a single string:
string file = "{ \"properties\": { \"displayName\": \"jayatestdefid\", \"description\": \"test assignment through API\", \"metadata\": { \"assignedBy\": \"xyz#gmail.com\" }, \"policyDefinitionId\": \"/providers/Microsoft.Management/managementgroups/MGTest/providers/Microsoft.Authorization/policyDefinitions/test\", \"parameters\": { \"ringValue\": { \"value\": [\"r0\"] } }, \"enforcementMode\": \"DoNotEnforce\", }}";
// Convert your json string into an instance of the RootObject class
RootObject jobject = JsonConvert.DeserializeObject<RootObject>(file);
// Get a list of all the "values"
List<string> values = jobject.properties.parameters.ringValue.value;
// Loop over your colleciton of "value" and do your logic
for (int i = 0; i < values.Count; ++i)
{
if (values[i] == "r0")
{
values[i] = "r0,r1";
}
}
// And finally, turn your object back into a json string
var result = JsonConvert.SerializeObject(jobject);
And this is the final result:
{
"properties":{
"displayName":"jayatestdefid",
"description":"test assignment through API",
"metadata":{
"assignedBy":"xyz#gmail.com"
},
"policyDefinitionId":"/providers/Microsoft.Management/managementgroups/MGTest/providers/Microsoft.Authorization/policyDefinitions/test",
"parameters":{
"ringValue":{
"value":[
"r0,r1"
]
}
},
"enforcementMode":"DoNotEnforce"
}
}

how to handle json object inside json object c#

I am sending URL request and getting response in curl and then convert into a json...object inside object(contain numeric and dot(924.136028459)) like:
string arr1 =
"{
"success":1,
"results":[
{
"Markets":{
"924.136028459":{
"productType":"BOOK1",
"key":"SB_MARKET:924.136028459"
},
"924.136028500":{
"productType":"BOOK2",
"key":"SB_MARKET:924.136028459"
}
}
}
]
}";
I have created properties class ..but i am not understanding how can we access inside "924.136028500" attributes
public class Json
{
public System.Collections.ObjectModel.Collection<Arr> results { get; set; }
}
public class Arr
{
public sp Markets { get; set; }
}
public class sp
{
public string productType { get; set; }
public string key { get; set; }
}
and I am using deserialize code...
var serializer = new JavaScriptSerializer();
Json json = serializer.Deserialize<Json>(arr1);
With Cinchoo ETL - an open source library, you can load the Market object easily with few lines of code
string json = #"{
""success"":1,
""results"":[
{
""Markets"":{
""924.136028459"":{
""productType"":""BOOK1"",
""key"":""SB_MARKET:924.136028459""
},
""924.136028500"":{
""productType"":""BOOK2"",
""key"":""SB_MARKET:924.136028459""
}
}
}
]
}
";
foreach (var rec in ChoJSONReader<sp>.LoadText(json).WithJSONPath("$..Markets.*"))
Console.WriteLine($"ProductType: {rec.productType}, Key: {rec.key}");
Output:
ProductType: BOOK1, Key: SB_MARKET:924.136028459
ProductType: BOOK2, Key: SB_MARKET:924.136028459
Checkout CodeProject article for some additional help.
Disclaimer: I'm the author of this library.

Deserialize JSON in C# to array

I'm having trouble doing deserialize a certain json I am collecting a website.
{
"query": {
"search": [
{
"ns": 0,
"title": "test",
"snippet": "test"
},
{
"ns": 0,
"title": "test2",
"snippet": "test2"
},
{
"ns": 0,
"title": "test3",
"snippet": "test3"
},
{
"ns": 0,
"title": "test4",
"snippet": "test4"
}
]
}
}
This is the class that I'm trying to deserialize into:
private void DesURL_Click(object sender, RoutedEventArgs e)
{
string url = #"https://pt.wikipedia.org/w/api.php.....";
var json = new WebClient().DownloadString(url);
var listaURL = JsonConvert.DeserializeObject<List<Query>>(json);
}
when trying to run the code of an error that this json should be deserialized into an array. Ai trying utiilizar JArray the method I need to do the deserialize before you can turn into array.
The goal is to convert the title and snippet to string in order to extract information from it.
Pro tip for you: Select your JSON and copy it to the clipboard. Now go to Visual Studio and on the Edit menu, Paste Special and then Paste JSON as Classes. that will give you this:
public class Rootobject
{
public Query query { get; set; }
}
public class Query
{
public Search[] search { get; set; }
}
public class Search
{
public int ns { get; set; }
public string title { get; set; }
public string snippet { get; set; }
}
And now you can deserialise like this:
var listaURL = JsonConvert.DeserializeObject<Rootobject>(json);
You need the following classes:
public class Rootobject
{
public Query query { get; set; }
}
public class Query
{
public Search[] search { get; set; }
}
public class Search
{
public int ns { get; set; }
public string title { get; set; }
public string snippet { get; set; }
}
Then you can deserialize like this:
var listUrl = JsonConvert.DeserializeObject<Rootobject>(json);
Your JSON is not an array. It contains a query object with a search property that has an array value.
So your class has to look something like this
public class ResponseDto {
public QueryDto Query {get; set;}
}
public class QueryDto {
public IEnumerable<Query> Search {get; set;}
}
var data = JsonConvert.DeserializeObject<QueryDto>(json);
var list = data.Query.Search.ToList();

Json parse sub-collection in c#

How can I do JSON in C# like the data below ?
{
"Aliases": [ "teddy", "freddy", "eddy", "Betty" ],
"Name":"reacher gilt",
"Address":"100 East Way",
"Age":74,
"Bars": {
"items": [
{
"Sub_Property1":"beep",
"Sub_Property2":"boop"
},
{
"Sub_Property1":"meep",
"Sub_Property2":"moop"
},
{
"Sub_Property1":"feep",
"Sub_Property2":"foop"
}
]
}
}
Actually my problem is inside the sub-collection. I saw someone did something
like this
person.Bars.Add("items",
new List<BarClass>(new[]{
new BarClass("beep","boop"),
new BarClass("meep","moop"),
new BarClass("feep","foop"),
}));
So, I have to add new BarClass("beep","boop"), but I need to do something
like this
String [] no1 = {1,2,3}
String [] no2 = {4,5,6}
person.Bars.Add("items",
new List<BarClass>(new[]{
for ()
{
new BarClass(no1[i],no2[i])
}
}));
How can i do this? Thanks and please help..
To read the JSON
The best way to read the whole JSON is to Deserialize it to a native C# object. If you do not already have the classes with your, you can create it in Visual Studio as
Copy your JSON text
Create a new empty class file in VS
Edit > Paste Special > Paste JSON As Classes
Here are the classes
public class Person
{
public string[] Aliases { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public int Age { get; set; }
public Bars Bars { get; set; }
}
public class Bars
{
public Item[] items { get; set; }
}
public class Item
{
public string Sub_Property1 { get; set; }
public string Sub_Property2 { get; set; }
}
Now you can use some .NET JSON library to deserialize. JSON.Net aka Newtonsoft JSON is a great library. You get get it from NuGet as well.
Then it's pretty easy to get the C# object from the JSON
//using Newtonsoft.Json;
var jsonString = File.ReadAllText(#"C:\YourDirectory\person.json");
var person = JsonConvert.DeserializeObject<Person>(jsonString);
If you want to read the sub-collection only, you can rather use Linq-to-JSON to read the items directly, like this
//using Newtonsoft.Json.Linq;
var jObject = JObject.Parse(jsonString);
List<Item> details = jObject["Bars"]["items"].ToObject<List<Item>>();
To create the JSON
You first need to create the object, then Serialize to JSON
string[] subProperties1 = new string[] { "1", "2", "3" };
string[] subProperties2 = new string[] { "4", "5", "6" };
Person person = new Person { Name = "Johny", Age = 7, Address = "Earth", Aliases = new string[] { "Sony", "Monty" } };
person.Bars = new Bars {
items = subProperties1.Zip(subProperties2,
(prop1, prop2) => new Item { Sub_Property1 = prop1, Sub_Property2 = prop2 })
.ToArray() };
var json = JsonConvert.SerializeObject(person);
To create the items from your existing string arrays, I have used IEnumerable.Zip function from Linq. You can read about them here.
This is the created JSON data
{
"Aliases": [ "Sony", "Monty" ],
"Name": "Johny",
"Address": "Earth",
"Age": 7,
"Bars": {
"items": [
{
"Sub_Property1": "1",
"Sub_Property2": "4"
},
{
"Sub_Property1": "2",
"Sub_Property2": "5"
},
{
"Sub_Property1": "3",
"Sub_Property2": "6"
}
]
}
}
You should create some classes
public class Person
{
public string Name {get;set;}
public string Address{get;set;}
public int Age {get;set;}
public Header {get;set;}
}
public class Header
{
public Detail[] Details {get;set;}
}
public class Detail
{
public string Sub1 {get;set;}
public string Sub2 {get;set;}
}
Create instance from Person class and initialize to instance after than
JavaScriptSerializer serializer =new JavaScriptSerializer();
var result=serializer.Serialize(instanceOfPerson);
"result" is json data
Assuming that you mean you want to create JSON string, you need to create those classes and use something like Newtonsoft JSON.net:
public class Item
{
public string Sub_Property1 { get; set; }
public string Sub_Property2 { get; set; }
}
public class Bars
{
public List<Item> items { get; set; }
}
public class Person
{
public List<string> Aliases { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public int Age { get; set; }
public Bars Bars { get; set; }
}
Please read the documentation here: http://www.newtonsoft.com/json/help/html/Introduction.htm

Categories

Resources