LINQ-TO-JSON cannot get value in array - c#

I am trying to get values with LINQ-TO-JSON in this JSON-TREE, So far it looks good until i've approached this categories element.
I want to get the value "Teknik" from this value and this is what i've tried to far without success.
Name = json["items"][i]["categories"].Children().Value<string>() ?? "Not assigned"
Name = json["items"][i]["categories"][0].Value<string>() ?? "Not assigned"
Name = json["items"][i]["categories"].First.Value<string>()
But none of these results works for me. Please help!

You didn't post the actual JSON string and the "tree" doesn't help. The JSON string in Querying JSON with LINQ could be represented with a similar tree, so I'll assume that's your source data:
string json = #"{
'channel': {
'title': 'James Newton-King',
'link': 'http://james.newtonking.com',
'description': 'James Newton-King\'s blog.',
'item': [
{
'title': 'Json.NET 1.3 + New license + Now on CodePlex',
'description': 'Annoucing the release of Json.NET 1.3, the MIT license and the source on CodePlex',
'link': 'http://james.newtonking.com/projects/json-net.aspx',
'categories': [
'Json.NET',
'CodePlex'
]
},
{
'title': 'LINQ to JSON beta',
'description': 'Annoucing LINQ to JSON',
'link': 'http://james.newtonking.com/projects/json-net.aspx',
'categories': [
'Json.NET',
'LINQ'
]
}
]
}
}";
JObject rss = JObject.Parse(json);
The example shows two ways to access values, through indexers or LINQ queries.
Using indexers, you'd only need [0] to access the first category of an item, eg:
rss["items"][i]["categories"][0];
That returns a JValue object as a JObject. You can cast it directly to string to get its value, eg:
(string)rss["items"][i]["categories"][0]
Or to a JValue, if you want to handle it as a JSON object and read the Value property, eg:
(rss["items"][i]["categories"][0] as JValue).Value;
A LINQ query wouldn't need indexers. If you wanted to retrieve the Category names you could write :
var query= from item in rss["channel"]["item"]
from category in item["categories"]
select new {Name=(string)category};
Or
var query = from category in rss["channel"]["item"].SelectMany(item=>item["categories"])
select new {Name=(string)category};
Or
var query = rss["channel"]["item"].SelectMany(item=>item["categories"])
.Select(category=>new {Name=(string)category});

Related

How to merge two json documents in json.net?

I'm not sure of the correct terminology as not overly knowledgeable about json. I have an existing json string/object of the following fixed format (i.e. all items are at the root level and of straightforward key/value pairs, although the number of items can vary):
{
"product_id": "1777",
"license_key": "ECHOES-SILENCE-PATIENCE-AND-GRACE",
"valid_for": "365",
"status": "active",
"times_activated_max": 1
}
I need a way to add a json string of varying schema/format that is passed into a method. This object can be of any json format. It's to be added to the root. For example adding this:
{
"name":"John",
"age":30,
"cars":["Ford", "BMW", "Fiat"]
}
..will become this:
{
"product_id": "1777",
"license_key": "ECHOES-SILENCE-PATIENCE-AND-GRACE",
"valid_for": "365",
"status": "active",
"times_activated_max": 1
"name":"John",
"age":30,
"cars":["Ford", "BMW", "Fiat"]
}
I have Newtonsoft.Json at my disposal for this.
I did read this but couldn't map it to my problem.
Hope someone can help
The JSON.NET documentation has an article just for that: Merging JSON. You can use JObject.Merge to merge two different objects into one:
JObject o1 = JObject.Parse(#"{
'FirstName': 'John',
'LastName': 'Smith',
'Enabled': false,
'Roles': [ 'User' ]
}");
JObject o2 = JObject.Parse(#"{
'Enabled': true,
'Roles': [ 'User', 'Admin' ]
}");
o1.Merge(o2, new JsonMergeSettings
{
// union array values together to avoid duplicates
MergeArrayHandling = MergeArrayHandling.Union
});
What you posted is two objects. A JSON document may be text, but what it contains are arrays and objects. "Merging" means finding a way to combine those objects/arrays and produce a new array or object.
Merge is defined by JContainer, the parent of both JObject and JArray. This means you can use Merge to merge both arrays and objects.
Another option with arrays is to use Enumerable.Union to combine the contents of both arrays, and create a new one :
var array1= JArray.Parse("[1,2,3]");
var array2= JArray.Parse("[3,4,5, \"a\"]");
var array3=new JArray(array1.Union(array2));
This returns [1,2,3,4,5,"a"]
Json.net uses the JObject type to represent arbitrary JSON objects. This has a handy Merge method for combining two JObjects.
Simply:
string s1 = #"
{
""product_id"": ""1777"",
""license_key"": ""ECHOES-SILENCE-PATIENCE-AND-GRACE"",
""valid_for"": ""365"",
""status"": ""active"",
""times_activated_max"": 1
}";
string s2 = #"
{
""name"":""John"",
""age"":30,
""cars"":[""Ford"", ""BMW"", ""Fiat""]
}";
JObject o1 = JObject.Parse(s1);
JObject o2 = JObject.Parse(s2);
o1.Merge(o2);
Console.WriteLine(o1);
See it here

How take this json path in newtonsoft.json C#

I have been building an application where JSON will be provided from a user API. It should read the data from the JSON using JSONPath and persist the selected portions. I am trying to do this using Json.Net (Newtonsoft). The following JSON is a sample:
{
// other properties here and different structure here
"Data": [
{
"Code": "625087",
"Name": "Customer Name",
"Email": "test#hfgidfgd.com"
},
{
"Code": "625087",
"Name": "Customer Name",
"Email": "test#hfgidfgd.com"
},
{
"Code": "625087",
"Name": "Customer Name",
"Email": "test#hfgidfgd.com"
}
],
// other properties here and different structure here
}
I would like to extract the array presented by the Data property content using JSONPath and convert it to List<Dictionary<string, object>> to manipulate in my application.
In tools like jsonpath.com the following JSONPath query works fine but with Newtonsoft it does not:
// get that json
string content = GetJson();
var jo = JObject.Parse(content);
var jsonPath = "$..Data.*";
var jsonPathResult = jo.SelectTokens(jsonPath, true /* to get error when it is not found */ );
Instead I got the exception:
Property '*' not valid on JArray.
If I do the JSONPath like this:
var jsonPath = "$..Data"; // same for just: "Data"
var jsonPathResult = jo.SelectTokens(jsonPath);
I have to loop on the result with two nested foreach, what I think it is not an elegant solution:
var result = new List<Dictionary<string, object>>();
foreach (var jsonResult in jsonPathResult)
{
foreach (var item in jsonResult)
{
var fields = JsonConvert.DeserializeObject<Dictionary<string, object>>(item.ToString());
// some adjusts on the fields dictionary will be applied here...
result.Add(fields);
}
}
Is there any way to get the result to take a single loop the only the content of Data property?
As shown in JSONPath - XPath for JSON, the syntax for an array element wildcard is [*]. Thus your code should look like:
var jsonPath = "$..Data[*]";
var result = jo.SelectTokens(jsonPath, true /* to get error when it is not found */ )
.Select(o => o.ToObject<Dictionary<string, object>>())
.ToList();
Here I am using JToken.ToObject<T>() to deserialize each array element directly to a Dictionary<string, object>> without re-serializing to a string.
Sample working .Net fiddle.

Deserialize Nested JSON with C# Without Class Declaration

I am trying to deserialize an object dynamically but unsure what the syntax is:
The JSON looks like this:
"Id": 2750,
"Rev": 1,
"Fields": {
"System.AreaPath": "test",
"System.TeamProject": "proj",
"System.IterationPath": "Ipath",
"System.WorkItemType": "type"
}
I know they can be accessed like this:
var resultString = response.Content.ReadAsStringAsync().Result;
var jsonObject = JObject.Parse(resultString);
string ID= jsonObject["id"].ToString();
But I am not sure how to get to the values nested in Fields directly.
I know I can iterate through jsonObject["Fields"] but I want to access them via something like jsonObject["Fields\\System.AreaPath"].ToString(); or whichever is the correct syntax, if it exists that is.

C# How to extract certain info long string

Okay I have been trying all day long with Regex and some other methods with no luck, here's what i'm trying to do i will try to make it as simple as I can, this an API and I am getting JSON response from my site like this:
{"user_id":1,"username":"xxx","email":"xxx#xxx.com","gender":"male","title":"","language_id":1,"timezone":"Africa\/Nairobi","visible":1,"activity_visible":1,"user_group_id":3,"secondary_group_ids":"2,4,6,8,11,12,13,16,19,20","message_count":235,"conversations_unread":0,"register_date":1424485355,"last_activity":1436186781,"trophy_points":43,"alerts_unread":2,"avatar_date":1435657653,"avatar_width":180,"avatar_height":224,"gravatar":"","user_state":"valid","is_moderator":0,"is_admin":1,"is_banned":0,"like_count":127,"warning_points":0,"is_staff":1,"advapps":"a:1:{i:0;a:2:{s:5:\"posid\";i:1;s:5:\"count\";i:5;}}","brms_statistic_perferences":"a:1:{i:1;s:1:\"0\";}","bratr_ratings":38,"tc_cui_icon":"","tc_cui_color":"#000000","breta_user_level":5,"breta_curent_level":34,"breta_next_level":45,"credits":"13402154377.480000","brc_points":"999999.000000","br_profile_image":"","br_cropy":"0.00",""}}
What i want to extract is user_group_id and secondary_group_ids then parse the numbers and add them to array then compare them with the given number, i want to check if the member is in that group number (secondary or primary does not matter).
How can i do that with the best and easiest way?
First, deserialize your JSON string to a .NET Dictionary. For example, with JSON.NET:
string json = #"[
{
'Name': 'Product 1',
'ExpiryDate': '2000-12-29T00:00Z',
'Price': 99.95,
'Sizes': null
},
{
'Name': 'Product 2',
'ExpiryDate': '2009-07-31T00:00Z',
'Price': 12.50,
'Sizes': null
}
]";
List<Product> products = JsonConvert.DeserializeObject<List<Product>>(json);
Console.WriteLine(products.Count);
// 2
Product p1 = products[0];
Console.WriteLine(p1.Name);
// Product 1
Then you can use basic LINQ queries against the Dictionary.
I suggest you use DataContractJsonSerializer to deserialize the Json string into a C# object.

c# dynamic json objects with dynamic names question

Before I get flagged for duplicate, I have the code from Dynamic json object with numerical keys working quite well now. The question with my numeric keys is that unfortunately, the JSON string I am getting is initially delimited by year, so would I use reflection to attempt to create a dynamic property on a dynamic object, and if so how? I know with a dynamic object I can't have obj["2010"] or obj[0]. In JavaScript this is no problem, just trying to get it working in C#. Ideas?
Example of JSON being returned:
{
"2010": [
{
"type": "vacation",
"alloc": "90.00"
},
Alternatively, sometimes the year is the second element as such:
I have no control over this json.
{
"year": [],
"2010": [
{
"type": "vacation",
"alloc": "0.00"
},
Maybe I'm misunderstanding your question, but here's how I'd do it:
static void Main(string[] args) {
var json = #"
{
'2010': [
{
'type': 'vacation',
'alloc': '90.00'
},
{
'type': 'something',
'alloc': '80.00'
}
]}";
var jss = new JavaScriptSerializer();
var obj = jss.Deserialize<dynamic>(json);
Console.WriteLine(obj["2010"][0]["type"]);
Console.Read();
}
Does this help?
I wrote a blog post on serializing/deserializing JSON with .NET: Quick JSON Serialization/Deserialization in C#
I have up-voted the question and JP's answer and am glad I dug around the internet to find this.
I have included a separate answer to simplify my use case for others to benefit from. The crux of it is:
dynamic myObj = JObject.Parse("<....json....>");
// The following sets give the same result
// Names (off the root)
string countryName = myObj.CountryName;
// Gives the same as
string countryName = myObj["CountryName"];
// Nested (Country capital cities off the root)
string capitalName = myObj.Capital.Name;
// Gives the same as
string capitalName = myObj["Capital"]["Name"];
// Gives the same as
string capitalName = myObj.Capital["Name"];
Now it all seems quite obvious but I just did not think of it.
Thanks again.

Categories