I have been kindly provided with the code below to convert a JSON array to a single object. I would like to use the same code to change multiple properties. All arrays will have a single object.
I would like to add some code that will walk through the JSON and execute the code below on any properties that have been found. Most properties are nested, hence the need to walk through the JSON.
// Load the JSON from a file into a JObject
JObject o1 = JObject.Parse(File.ReadAllText(#"output.json"));
// Get the desired property whose value is to be replaced
var prop = o1.Property("to_Description");
// Replace the property value with the first child JObject of the existing value
prop.Value = prop.Value.Children<JObject>().FirstOrDefault();
// write the changed JSON back to the original file
File.WriteAllText(#"output.json", o1.ToString());
Replace the middle two lines with these:
// Find all properties anywhere in the JSON whose values are arrays
var arrayProperties = o1.Descendants()
.OfType<JProperty>()
.Where(p => p.Value.Type == JTokenType.Array);
foreach (JProperty prop in arrayProperties)
{
// Replace the property value with the first child JObject of the existing value
prop.Value = prop.Value.Children<JObject>().FirstOrDefault();
}
Fiddle: https://dotnetfiddle.net/iP8Ibd
Related
So I am able to retrieve the elements.handle but i am unable to retrieve elements.handle~. Is there any possible way to do so?
I've tried escape character elements['handle\~'] but it does not seem to work
{"elements":[{"handle":"urn:li:emailAddres:7440721026","handle~":{"emailAddress":"abc#gmail.com"}}]}
Since the value you are looking for (abc#gmail.com) is nested a few layers deep. If you want to retrieve it, you'll need to access it accordingly.
var data = "{\"elements\":[{\"handle\":\"urn:li:emailAddres:7440721026\",\"handle~\":{\"emailAddress\":\"abc#gmail.com\"}}]}";
dynamic x = JsonConvert.DeserializeObject(data);
// x is an object with one property: elements
Console.WriteLine($"x: {x}");
// x.elements is a List (based on your question)
Console.WriteLine($"x.elements: {x.elements}");
// x.elements[0] is a Dictionary (based on your question)
Console.WriteLine($"x.elements[0]: {x.elements[0]}");
// x.elements[0]["handle~"] is another Dictionary
Console.WriteLine($"x.elements[0][handle~]: {x.elements[0]["handle~"]}");
// x.elements[0]["handle~"]["emailAddress"] is the value you want
Console.WriteLine($"x.elements[0][handle~][emailAddress]: {x.elements[0]["handle~"]["emailAddress"]}");
That means x.elements[0]["handle~"]["emailAddress"] should get you abc#gmail.com.
I have a json string that I would like to iterate through to retrieve a specific value. In this object, there are multiple items, each with the same elements. What i am trying to do is search through each item for its request_item.u_requested_for.user_name, and compare it to a different value. If it does NOT match, move on. If it does match, then i want to retrieve the request_item.u_requested_for.sys_id value. Additionally, the size of the json will not always be the same. Sometimes there will be 5 elements, other times 20. How can I loop through each item, do the comparison, and then retrieve the other value that I need?
I've played around with this using other ideas I've found, but I'm unable to really get it working. First, should i parse the string into an object using JObject.Parse()? Or should I continue working with this as as string?
I've tried using a JsonTextReader to read through each line, but I'm unsure how I would retrieve the value I need once I find the item that matches the criteria.
{
"result": [
{
"request_item.sys_id": "db6e3306dbc3ef8c791a777a8c961986",
"request_item.u_requested_for.sys_id": "8416ccb3dba9df8c1ddee3a84b961911",
"request_item.u_requested_for.user_name": "H298956"
},
{
"request_item.sys_id": "e5990f89db47ebc8bd663ebd7c96198f",
"request_item.u_requested_for.sys_id": "878ce1d5dbcd0300cc78dd0b5e961987",
"request_item.u_requested_for.user_name": "E092733"
},
{
"request_item.sys_id": "87970c08db4be388791a777a8c9619ee",
"request_item.u_requested_for.sys_id": "484a1cf5db5f83c04f6489584b961952",
"request_item.u_requested_for.user_name": "H281111"
}
]
}
In this case, I want to iterate through each item and look for the value "H281111". Once I find that value, I want to extract the "request_item.u_requested_for.sys_id value", which in this case is "484a1cf5db5f83c04f6489584b961952".
Depending on your requirements, you may want a much quicker and dirtier solution than Michaƫl's. If the contents of this JSON string are used in multiple places in your application, I urge you to write the classes and deserialize properly as he suggests. You'll be glad you did.
But if you only need one value from this JSON string in one place, this will work.
var jobj = JObject.Parse(json);
var user_name = "H281111";
var sys_id = jobj["result"]
.Where(r => (String)r["request_item.u_requested_for.user_name"] == user_name)
.Select(r => (String)r["request_item.u_requested_for.sys_id"])
.FirstOrDefault();
Elphas Tori suggests the following improvement using the ?[] (null-conditional element access) operator:
var sys_id2 = (string)jobj["result"]
.FirstOrDefault(r =>(string)r["request_item.u_requested_for.user_name"] == user_name)
?["request_item.u_requested_for.sys_id"];
If that LINQ code looks too much like gibberish to you, you can use a more conventional loop approach:
foreach (var r in jobj["result"])
{
// etc.
}
I think you should have a class representing the objects in this Json file, deserialize the Json file into your class and then use LINQ to find what you need in your list of objects.
Result would be an array of requestItem
Request item would have the following fields :
sys_id
u_requested_for (Class)
Requested for would have the following fields :
sys_id
user_name
You can even be fancy and use a base class that has sys_id in it to save some time.
You need to deserialize this into POCO objects to iterate them. Here you can find an example how to implement it.
I m trying to populate class object from excel.I received values in json which i m deserializing but i dont want to get List
because in handler class there is function that is of type policy how i can map PolicyNew to class object without List.
var json = JsonConvert.SerializeObject(query);
var policynew = JsonConvert.DeserializeObject<List<PolicyNew>>(json);
Policy policy = Handler.GeneratePolicy(policynew);
//Handler.cs
Handler.GeneratePolicy(PolicyNew policynew)
{
}
If your jsonstring contains an array, you have to deserialize to some sort of List/Array. If you know, you will only need a single element of that list (or you know, that list only contains one element) you can just take the first element of the resulting list.
var policynew = JsonConvert.DeserializeObject<List<PolicyNew>>(json).FirstOrDefault();
If you have control over the generation of the json string, you could change the serialization and not create an array [{"p1": 3, ...}] but a single object {"p1": 3, ...}
I have a JArray with objects have two property. For example:
[
{"Prop1":"key1", "Prop2":"value1"},
{"Prop1":"key2", "Prop2":"value2"},
{"Prop1":"key3", "Prop2":"value3"}
]
And I need to KeyValuePair (or Dictionary doesn't matter) structure in C# such as
key1-value1
key2-value2
key3-value3
Names of Prop1 and Prop2 also can change which means that JArray can have different prop names but number of properties in the object always will be 2. So that I need general method which deserialize the JArray to List<KeyValuePair> .
Given a variable array of type JArray, you can do the following using extension methods from the System.Linq namespace:
var pairs = array
// Cast array items from JToken to JObject.
// You could filter instead using `OfType<JObject>() if nulls might be present
.Cast<JObject>()
// Convert the first and second property values to a KeyValuePair
.Select(o => new KeyValuePair<string, string>((string)o.PropertyValues().ElementAtOrDefault(0),
(string)o.PropertyValues().ElementAtOrDefault(1)))
.ToList();
var dict = pairs.ToDictionary(p => p.Key, p => p.Value);
Sample fiddle
I suppose this is another entry in my series of questions, but I'm stuck again. This time, I'm having trouble working with a JArray of JObjects and determining the Property.Value type for each element in the JArray...
My code is here:
https://dotnetfiddle.net/bRcSAQ
The difference between my previous questions and this question is that my outer Linq query gets both JObject and JArray tokens, so that's why I have an if (jo is JObject) at Line 40 and a if (jo is JArray) at Line 48.
Once I know I have a JArray of <JObjects>, I have code that looks like this (Lines 48-):
if (jo is JArray)
{
var items = jo.Children<JObject>();
// return a JObject object
}
When I use a debugger and look at items, I see that it contains 3 JObject objects--one for Item_3A1, Item_3A2, and Item3A3. But I need to know the JTokenType for each JProperty.Value because I am interested only in Property values of type JTokenType.String.
So I tried:
// doesn't work :(
var items = jo.Children<JObject>()
.Where(p => p.Value.Type == JTokenType.String);
The compiler red-lines the Value property with the error CS0119 'JToken.Value<T>(object)' is a method, which is not valid in the given context.
I realize that "p" in the Linq express is not a JProperty. I guess it's a JObject. And I don't know how to cast "p" so that I can examine the type of JProperty object it represents.
Ultimately, I need the code for JArray processing (starting at Line 48) to add an return a JObject that contains an JSON array composed only of JProperty objects of type JTokenType.String. This means that given the sample JSON, it first should return a JObject holding these JSON properties:
{ ""Item_3A1"": ""Desc_3A1"" },
{ ""Item_3A2"": ""Desc_3A2"" },
{ ""Item_3A3"": ""Desc_3A3"" }
On the next iteration, it should return a JObject holding these JSON properties (notice that the nested Array3B1 properties are omitted because Array3B1 is not a JProperty with a Value type of JTokenType.String):
{ ""Item_3B1"": ""Desc_3B1"" },
{ ""Item_3B2"": ""Desc_3B2"" },
The third iteration would contain:
{ ""Item_3B11"": ""Desc_3B11"" },
{ ""Item_3B12"": ""Desc_3B12"" },
{ ""Item_3B13"": ""Desc_3B13"" }
And the fourth (final) iteration would contain:
{ ""Item_3C1"": ""Desc_3C1"" },
{ ""Item_3C2"": ""Desc_3C2"" },
{ ""Item_3C3"": ""Desc_3C3"" }
This might be my final hurdle in this "series".
Sincere thanks to anyone who can and will help--and a special thanks again to users "Brian Rogers" and "dbc" for their truly amazing JSON.NET/Linq knowledge.
This produces the output you require:
var root = (JContainer)JToken.Parse(json);
var query = root.Descendants()
.Where(jt => (jt.Type == JTokenType.Object) || (jt.Type == JTokenType.Array))
.Select(jo =>
{
if (jo is JObject)
{
if (jo.Parent != null && jo.Parent.Type == JTokenType.Array)
return null;
// No help needed in this section
// populate and return a JObject for the List<JObject> result
// next line appears for compilation purposes only--I actually want a populated JObject to be returned
return new JObject();
}
if (jo is JArray)
{
var items = jo.Children<JObject>().SelectMany(o => o.Properties()).Where(p => p.Value.Type == JTokenType.String);
return new JObject(items);
}
return null;
})
.Where(jo => jo != null)
.ToList();
Here I use SelectMany() to flatten the nested enumeration of properties of the enumeration of child objects of jo to a single enumeration of all properties of child objects. o => o.Properties() is a lambda expression mapping the JObject o to its collection of properties, and p => p.Value.Type == JTokenType.String is another lambda mapping a property p (generated by the previous SelectMany clause) to a true/false value indicating whether the property has a string value. Both o and p are lambda input parameters that are implicitly typed.
Also, in the // No help needed in this section section, objects whose parents are arrays are skipped, since they will get collected by the (jo is JArray) clause.
Note that if different children of the jo array happen to have identical property names, the JObject constructor may throw a duplicated key exception.
Forked fiddle.