I have three different arrays which I want to merge them into a single object.
array 1 : [{"Id":1,"Number":"1234","Category":"Chocalte", "Status": "Error"}]
heatingissues: [{"myId":3,"Id":"5801"}]
problemissue: [{"myId":1,"Id":2,"Name":"Desktop"}]
I want result to be like this:
{
"Id": 3,
"Number": "1190042293",
"Category": "Chocalte",
"heatingissues": [
{
"myId": 3,
"id": "5801"
}
],
"problemissue": [
{
"myId": 1,
"name": "Desktop"
}
]
}
After deserializing all the arrays individually (respectively to the results and problemissueresults variables) I try:
var j = JsonConvert.SerializeObject(new{
results,
heatingissues= problemissueresults,
problemissue= problemissueresults
});
Which generates the following output:
{
"results": [
{
"id": 3,
"Number": "1190042293",
"category": "Chocalte"
}
],
"heatingissues": [
{
"myId": 3,
"id": "5801"
}
],
"problemissue": [
{
"myId": 1,
"name": "Desktop"
}
]
}
How can I avoid these results?
In this case, you need to declare explicitly the properties of the object you are serializing to match the format you want.
In words of the documentation for C# Anonymous Types:
If you do not specify member names in the anonymous type, the compiler gives the anonymous type members the same name as the property being used to initialize them
So your result was being serialized as an array with a json key of the same name.
Try this:
var obj =
new
{
id = results[0].id,
number = results[0].number,
category = results[0].category,
heatingissues= problemissueresults,
problemissue= problemissueresults
};
var j = JsonConvert.SerializeObject(obj);
Newtonsoft json library support merging operation.
http://www.newtonsoft.com/json/help/html/MergeJson.htm
Related
What has been done so far?
I am working on dividing up the number of records into 3 batches and processing them in parallel to increase the performance. However, after processing the batches in parallel I would also like to save the outcome (JSON string) of the processed records in a variable.
As you can see below, I first initialize the variable as List of string and then run the foreach loop which saves the processed outcome as mentioned below.
List<string> responseOutcome = new List<string>();
Parallel.ForEach(recordBatches, batch => {
responseOutcome.Add(response1.Content);
});
Result in List responseOutcome comes as:
responseOutcome[0]
[
{
"Name": "Sample1",
"ID": "123"
},
{
"Name": "Sample2",
"ID": "394"
}
],
responseOutcome[1]
[
{
"Name": "Sample5",
"ID": "384"
},
{
"Name": "Sample6",
"ID": "495"
}
],
responseOutcome[2]
[
{
"Name": "Sample3",
"ID": "473"
},
{
"Name": "Sample4",
"ID": "264"
}
]
What I would like to achieve?
Now I would like to take the value of responseOutcome which is multiple arrays of JSON string and merge them into one big JSON string.
Final Output
[
{
"Name": "Sample1",
"ID": "123"
},
{
"Name": "Sample2",
"ID": "394"
},
{
"Name": "Sample5",
"ID": "384"
},
{
"Name": "Sample6",
"ID": "495"
},
{
"Name": "Sample3",
"ID": "473"
},
{
"Name": "Sample4",
"ID": "264"
}
]
I looked into several similar cases but they weren't nearly similar. Like:
How do I merge multiple json objects
How do I combine two arrays from two JObjects in Newtonsoft JSON.Net?
Any help/guidance will be great!!
Using Newtonsoft, you can create a JArray from each of your responses. Then you can flatten the hierarchy using linq's SelectMany method and re-serialize the object.
Try this:
var obj = responses.Select(r => JArray.Parse(r.Trim(','))).SelectMany(token => token);
string json = JsonConvert.SerializeObject(obj, Formatting.Indented);
There are probably more efficient ways to do this if you want to do pure string manipulation, but using Newtonsoft, I would deserialize, merge and then re-serialize.
Create a small POCO model:
public class ResponseOutcomeModel
{
public string ID { get; set; }
public string Name { get; set; }
}
Then deserialize to this model, merge and reserialize to JSON as a single list.
var outcomeList = new List<ResponseOutcomeModel>();
foreach (var i in responseOutcome)
{
outcomeList.AddRange(JsonConvert.DeserializeObject<List<ResponseOutcomeModel>>(i.Trim().TrimEnd(',')));
}
var finalJson = JsonConvert.SerializeObject(outcomeList);
Note, the Time/TrimEnd is used if the trailing commas in your example are really there in your responseOutcome array (at the end of each element in the array). The call to DeserializeObject will complain if you leave the commas in there.
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.
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);
Suppose I have this simple object definition:
public class Item
{
public int section { get; set; }
public string item { get; set; }
}
I have some data in a single-depth array. This is JSON, which would be converted to C# objects via Json.NET:
[
{
"section": 0,
"item": "Hello!"
},
{
"section": 1,
"item": "First Steps"
},
{
"section": 1,
"item": "How to Ask for Help"
},
{
"section": 2,
"item": "Your First Program"
},
{
"section": 2,
"item": "The Code"
},
{
"section": 2,
"item": "How It Works"
},
{
"section": 3,
"item": "Where To Go From Here"
}
]
Using Entity Framework or some other method, I have arrived at a simple list of these objects as stated above, contained within a var variable.
Now what I want to do is get the same list, but where each section is grouped as an array within the outer array. For example, the JSON of what I want looks like this:
[
[
{
"section": 0,
"item": "Hello!"
}
],
[
{
"section": 1,
"item": "First Steps"
},
{
"section": 1,
"item": "How to Ask for Help"
}
],
[
{
"section": 2,
"item": "Your First Program"
},
{
"section": 2,
"item": "The Code"
},
{
"section": 2,
"item": "How It Works"
}
],
[
{
"section": 3,
"item": "Where To Go From Here"
}
]
]
My initial thought was to do something with a LINQ query using the groupby statement but I don't think this is what I'm looking for - groupby seems to be analogous to the SQL version so it can only be used for aggregate operations.
The only other option I have found so far is to use a LINQ query to get a list of all of the sections:
var allSections = (from x in myData select x.section).Distinct();
...and then iterate through those IDs and manually build the array:
List<List<Item>> mainList = new List<List<Item>>();
foreach (int thisSection in allSections.ToArray())
{
List<Item> thisSectionsItems = (from x in myData where x.section == thisSection select x).ToList();
mainList.Add(thisSectionsItems);
}
return mainList;
This should result in a proper enumerable that I can feed into JSON.NET and get the expected result, but this seems inefficient.
Is there a more LINQ-ish, or at least more efficient, way to split the items into groups?
You can certainly achieve this with .GroupBy()
var grouped = items
.GroupBy(x => x.section) // group by section
.Select(x => x.ToArray()) // build the inner arrays
.ToArray(); // return collection of arrays as an array
I have an object that I am converting to JSON to be consumed by Ember.js.
Currently I have some child objects that are fully expanded but ember expects
just an array of ids on the client side. How can I flatten the object out to
be a int[]
items = Mapper.Map<IList<Item>>(client.GetItems());
foreach (var item in items)
{
int[] choices = item.Choices.Select(x => x.Id).ToArray();
item.Choices = choices;
}
get an error about not being able to convert to type int[] from IList<Item>
how can I cast the property?
example current JSON I produce after serializing
{ "items": [
{
"id": 0,
"name": "Item0",
"description": "...",
"choices": [
{ "id": 0, "property": "somevalue" },
{ "id": 1, "property": "somevalue" },
]
},
{
"id": 1,
"name": "Item1",
"description": "...",
"choices": [
{ "id": 0, "property": "somevalue" },
{ "id": 1, "property": "somevalue" },
]
}
]}
The JSON I would like to produce
{ "items": [
{
"id": 0,
"name": "Item0",
"description": "...",
"choices": [0, 1]
},
{
"id": 1,
"name": "Item1",
"description": "...",
"choices": [0, 1]
}
]}
SelectMany flattens List of Lists and produces single List with all items.
items.SelectMany(x=>x.Choices.Select(y=>y.Id).ToArray()));
get an error about not being able to convert to type int[] from IList how can I cast the property?
You cannot cast one type to another. Instead you can create another property of type int[] in your class and use the LINQ statement in getter (with necessary validation checks).
public int[] ChoiceIDs
{
get {
return this.Choices.Select(x => x.Id).ToArray();
}
}