How to update JArray values with C# and Json.NET - c#

I'm getting an array of items from Web API (lines before this are omitted):
var cars = JArray.Parse(response.Content.ReadAsStringAsync().Result)
Inside the cars JArray it looks like this:
"cars": [{
"id": 1,
"make": "Audi",
"color": "red"
}, {
"id": 2,
"make": "Mercedes",
"color": "red"
}, {
"id": 3,
"make": "Ford",
"color": "yellow"
}]
I would like to update the color of Ford to red if Audi is also red.
How can I do that with C# and Json.NET?

The JSON you provided is not valid for me to parse, so ive made an assumption to demonstrate. which wraps your sample in a root JSON object.
You can query the JOBject using keys. i.e to access cars propery in the JSON you can use o["cars"]. With this approach you can see i use a bit of Linq to figure out if Audi is red, and if so, you can perform direct modifications to the o object and set values accordingly.
This is the most basic approach, without any further code.
void Main()
{
var json = #"
{
""cars"": [
{ ""id"": 1, ""make"": ""Audi"", ""color"": ""red"" },
{ ""id"": 2, ""make"": ""Mercedes"", ""color"": ""red"" },
{ ""id"": 3, ""make"": ""Ford"", ""color"": ""yellow"" }
]
}";
var jObject = Newtonsoft.Json.Linq.JObject.Parse(json);
var jArray = jObject["cars"] as JArray;
Console.WriteLine("Before: " + JsonConvert.SerializeObject(jObject));
var audiIsRed = jArray.Any(car => car.Value<string>("make").Equals("Audi") && car.Value<string>("color").Equals("red"));
if (audiIsRed)
{
jArray.First(c => c.Value<string>("make").Equals("Ford"))["color"] = "red";
}
Console.WriteLine("After: " + JsonConvert.SerializeObject(jObject));
}
An alternative could be making a POCO to deserialize the results, which would contain, for example a List<Car> and then you could do all modifications with C# and no JSON.NET then serialize that result back to JSON.

Related

Looping through JObject nested array

I can not figure out exactly how to did through this JObject in order to retrieve the id property under runs.
I have this following code which will successfully give me the id property that is under entries, but how can I nest this again to go into the runs sections and get those ID's?
JSON:
{
"id": 168,
"name": "section 1",
"entries": [
{
"id": "908-9876-908",
"suite_id": 15,
"name": "List 1",
"runs": [
{
"id": 169,
"suite_id": 15
}
]
},
{
"id": "998-4344-439",
"suite_id": 16,
"name": "List 2",
"runs": [
{
"id": 170,
"suite_id": 16
}
]
}
]
}
C# Code:
JObject obj = JsonConvert.DeserializeObject<JObject>(response);
foreach (JObject id in obj["entries"])
{
string returnable = (string)id["id"];
Console.WriteLine(returnable);
}
I have tried looking at ["entries"]["runs"] but that also was not working.
The print out of this is:
908-9876-908
998-4344-439
What I would like is
169
170
You can achieve it using the following code
var jsonObject = JObject.Parse(json);
foreach (var entry in jsonObject["entries"])
{
foreach (var run in entry["runs"])
{
string returnable = (string)run["id"];
Console.WriteLine(returnable);
}
}
You would like to see
169
170
They are an id values from runs array, therefore you should enumerate them in the inner loop. You've also missed a comma after "name": "section 1"
You can use SelectTokens() to query for nested data inside a JToken hierarchy. It provides support for JSONPath queries including wildcards [*] for arrays:
var ids = obj.SelectTokens("entries[*].runs[*].id").Select(i => (long)i).ToList();
See: Querying JSON with complex JSON Path.
Demo fiddle here.

Convert a list of JToken to a list of one of the values

I have a list of json JTokens:
List<JToken> subjectresults = jObj[jp]["subjects"].Children().ToList();
Note that my jp is var jp = jObj.Properties().First().Name; because the name is dynamic.
Each of the tokens contains two further items, a url and a name.
I want to get a list of strings that contains just the name value, from this list of jtokens.
So that:
[0]: {{
"url": "https://openlibrary.org/subjects/science",
"name": "Science"
}}
[1]: {{
"url": "https://openlibrary.org/subjects/in_library",
"name": "In library"
}}
Becomes:
{"Science", "In library"}
I can't seem to figure out the syntax.
Or alternatively how do I skip the tokens and go right to my list.
I didn't strongly type this, because the parent property has the dynamic name, and I only needed a couple of the fields.
I suppose that subjects-property is Array:
var jObj = JObject.Parse(json);
var jp = jObj.Properties().First().Name;
var subjectresults = jObj[jp]["subjects"]
.Children()
.Select(v => v["name"].Value<string>())
.ToArray();
/*
subjectresults
{string[2]}
[0] [string]:"Science"
[1] [string]:"In library"
*/
The source json:
var json = #"{
""name"": {
""subjects"": [
{
""url"": ""https://openlibrary.org/subjects/science"",
""name"": ""Science""
},
{
""url"": ""https://openlibrary.org/subjects/in_library"",
""name"": ""In library""
}
]
}
}";

Linq query to Json string

starting from a JObject I can get the array that interests me:
JArray partial = (JArray)rssAlbumMetadata["tracks"]["items"];
First question: "partial" contains a lot of attributes I'm not interested on.
How can I get only what I need?
Second question: once succeeded in the first task I'll get a JArray of duplicated items. How can I get only the unique ones ?
The result should be something like
{
'composer': [
{
'id': '51523',
'name': 'Modest Mussorgsky'
},
{
'id': '228918',
'name': 'Sergey Prokofiev'
},
]
}
Let me start from something like:
[
{
"id": 32837732,
"composer": {
"id": 245,
"name": "George Gershwin"
},
"title": "Of Thee I Sing: Overture (radio version)"
},
{
"id": 32837735,
"composer": {
"id": 245,
"name": "George Gershwin"
},
"title": "Concerto in F : I. Allegro"
},
{
"id": 32837739,
"composer": {
"id": 245,
"name": "George Gershwin"
},
"title": "Concerto in F : II. Adagio"
}
]
First question:
How can I get only what I need?
There is no magic, you need to read the whole JSON string and then query the object to find what you are looking for. It is not possible to read part of the JSON if that is what you need. You have not provided an example of what the data looks like so not possible to specify how to query.
Second question which I guess is: How to de-duplicate contents of an array of object?
Again, I do not have full view of your objects but this example should be able to show you - using Linq as you requested:
var items = new []{new {id=1, name="ali"}, new {id=2, name="ostad"}, new {id=1, name="ali"}};
var dedup = items.GroupBy(x=> x.id).Select(y => y.First()).ToList();
Console.WriteLine(dedup);

Read all dynamic name and value from JSON string

I need to get all dynamic name and values from JSON string. I am going to create one function with JSON string parameter. that parameter JSON string name and values can change, But I need to print all names and values from that JSON string.
Example code :
json : { "data":
[{
"id": "001",
"Name": "Somu",
"Address": "Erode",
},
{
"id": "002",
"Name": "Ajal",
"Address": "USA",
}]
}
I want to Get all values from this JSON with in loop. Property name may change or increase property count.I need to get all values from passed JSON.
Expected Result : 1 st loop
Id = 001
Name =Somu
Address =Erode
2 nd loop
Id = 002
Name =Ajal
Address =USA
Using Json.Net
string json = #"{ ""data"": [ { ""id"": ""001"", ""Name"": ""Somu"", ""Address"": ""Erode"", }, { ""id"": ""002"", ""Name"": ""Ajal"", ""Address"": ""USA"", }] }";
var result = JObject.Parse(json)
["data"]
.Select(x => new
{
id = (string)x["id"],
Name = (string)x["Name"],
Address = (string)x["Address"],
})
.ToList();
or more dynamic versions
var result = JObject.Parse(json)
["data"]
.Select(x=> x.Children().Cast<JProperty>()
.ToDictionary(p=>p.Name,p=>(string)p.Value))
.ToList();
.
var result = JObject.Parse(json)["data"]
.ToObject<List<Dictionary<string,string>>>();

JSON.NET reader problem

i got some problem when i generate .json file from spring .json ,and i got this format
{ "models": [
{
"id":1,
"modelName":"dfdsf",
"created":{
"userFullname":"demo",
"time":"150301",
"date":"20110208",
"userId":"123"
},
"remark":"dsfdf",
"updated":"~unique-id~1"
},
{
"id":2,
"modelName":"test",
"created":{
"userFullname":"test",
"time":"150301",
"date":"20110210",
"userId":"124"
},
"remark":"test",
"updated":{
"userFullname":"test",
"time":"150301",
"date":"20110209",
"userId":"test"
}
}
]}
first time i used JObject Parse for convert
JObject job = JObject.Parse(fullJson);
and the other hand i used jtoken to focus "models"
JToken jDetail = job["models"];
but the problem is {[{ xxx }]} it look like jarray i don't have any idea to convert it
i ever use JArray, JsonTextReader but it doesn't work.
could suggestion some? because if i pass this ll i set some value to object.
thank you for every idea.
string fullJson = File.ReadAllText("TextFile1.txt"); // for brevity
var job = JObject.Parse(fullJson);
var models = job.Value<JArray>("models");
Console.WriteLine(models[0]);
result:
{
"id": 1,
"modelName": "dfdsf",
"created": {
"userFullname": "demo",
"time": "150301",
"date": "20110208",
"userId": "123"
},
"remark": "dsfdf",
"updated": "~unique-id~1"
}

Categories