How to properly deserialize and iterate over an array of JSON objects - c#

In my app, I'm getting some data in a string format, which I'm converting to json:
string stringValue = System.Text.Encoding.Default.GetString(message.Value);
var jsonValue = JsonConvert.DeserializeObject(stringValue);
The resulting json string looks like this:
[
{
"LOCATION_ID": 2800,
"CITY": "Sao Paulo"
},
{
"LOCATION_ID": 1700,
"CITY": "Seattle"
},
{
"LOCATION_ID": 2300,
"CITY": "Singapore"
},
{
"LOCATION_ID": 1600,
"CITY": "South Brunswick"
},
{
"LOCATION_ID": 1500,
"CITY": "South San Francisco"
},
{
"LOCATION_ID": 1400,
"CITY": "Southlake"
},
{
"LOCATION_ID": 2600,
"CITY": "Stretford"
},
{
"LOCATION_ID": 2200,
"CITY": "Sydney"
}
]
What syntax can I use to iterate over this json array, and print out one json object at a time?

What syntax can I use to iterate over this json array, and print out
one json object at a time?
Define a model:
public class MyModel
{
public int LOCATION_ID { get; set; }
public string CITY { get; set; }
}
and then deserialize to this model:
var models = JsonConvert.DeserializeObject<IList<MyModel>>(stringValue);
and now you are free to iterate with standard C# iteration constructs like the foreach keyword:
foreach (MyModel model in models)
{
Console.WriteLine(model.LOCATION_ID);
Console.WriteLine(model.CITY);
}

The easiest way is to use dynamics as follows.
Note, this method reduces code footprint and is more readable the alternative approaches:
var json = #"[
{
'LOCATION_ID': 2800,
'CITY': 'Sao Paulo'
},
{
'LOCATION_ID': 1700,
'CITY': 'Seattle'
}
]";
dynamic parsedArray = JsonConvert.DeserializeObject(json);
foreach (dynamic item in parsedArray)
Debug.WriteLine($"Location ID: {item.LOCATION_ID} City: {item.CITY}");

Darin Dimitrov is spot on answer.
Another alternative, if you don't really want strongly model, is using Dictionary and its qualities.
var jsonObj = JsonConvert.DeserializeObject<Dictionary<string, string>[]>(stringValue);
foreach (var obj in jsonObj)
{
Console.WriteLine("{0}: {1}", obj["LOCATION_ID"], obj["CITY"]);
}

Related

Convert JSON tree structure to list

I am new to JSON. I have a JSON list in a tree structure like below:
{
"complaint#simulator.amazonses.com": {
"time": "2018-01-02T20:45:46.65Z",
"type": "Complaint",
"bounceType": "null",
"bounceSubType": "null"
},
"struax#example.org": {
"time": "2018-01-02T20:53:03Z",
"type": "Bounce",
"bounceType": "Permanent",
"bounceSubType": "Suppressed"
},
"bounce-test#service.socketlabs.com": {
"time": "2018-01-02T21:06:40.097Z",
"type": "Bounce",
"bounceType": "Permanent",
"bounceSubType": "Suppressed"
},
"bounce#simulator.amazonses.com": {
"time": "2018-01-02T21:08:02Z",
"type": "Bounce",
"bounceType": "Permanent",
"bounceSubType": "General"
},
"jstrechay#example.org": {
"time": "2018-01-05T06:31:39Z",
"type": "Bounce",
"bounceType": "Permanent",
"bounceSubType": "General"
},
"leematt45#example.org": {
"time": "2018-01-05T06:49:13Z",
"type": "Bounce",
"bounceType": "Permanent",
"bounceSubType": "Suppressed"
},
"afbweb#example.org": {
"time": "2018-01-07T12:50:38Z",
"type": "Bounce",
"bounceType": "Transient",
"bounceSubType": "General"
},
"bajanina2013#example.org": {
"time": "2018-01-02T08:12:19Z",
"type": "Bounce",
"bounceType": "Transient",
"bounceSubType": "MailboxFull"
},
"martin.bunt#example.org": {
"time": "2018-01-05T07:00:24Z",
"type": "Complaint",
"bounceType": "null",
"bounceSubType": "null"
}
}
My SQL table columns are Email, time, type, bounceType, and bounceSubType.
How can I extract data from the JSON list and save it in the DB?
I am using this code:
string JSON = response.Content.ReadAsStringAsync().Result;
var jObj = (JObject)JsonConvert.DeserializeObject(JSON);
The JSON is in a tree structure and I am not able to fetch the parent node and the respective child in a list.
Here is what I would do. First, define a model class to hold the item data (you might already have such a class):
class BounceItem
{
public string Email { get; set; }
public DateTime Time { get; set; }
public string Type { get; set; }
public string BounceType { get; set; }
public string BounceSubType { get; set; }
}
Next, deserialize the JSON into a Dictionary<string, BounceItem>:
var dict = JsonConvert.DeserializeObject<Dictionary<string, BounceItem>>(json);
The email addresses will become the keys in the dictionary, and values will be BounceItem objects containing the nested properties. However, notice that the Email property in each BounceItem will not be populated at this point.
To fix that, post-process the dictionary to copy each key into the Email property on the corresponding item, storing results into a List<BounceItem>:
var list = dict.Select(kvp => { kvp.Value.Email = kvp.Key; return kvp.Value; }).ToList();
Now you have a list of model objects which should match up to your SQL table, and you can insert them using whatever method is appropriate for your database of choice.
Fiddle: https://dotnetfiddle.net/5rzyCs
It's pretty simple using Json.NET or using Newtonsoft.Json.Linq, if you are using c#.NET.
First Method:
dynamic jsonObject = JsonConvert.DeserializeObject("your json string");
Second Method:
dynamic jsonObject = JObject.Parse("your json string");
After parsing you can pass the jsonObject to the DB.
You need to create a class based on your Json Responce. Than from that class deserialize your object like this
Class1 class1Object = JsonConvert.DeserializeObject<Class1>(str)

There is no argument that corresponds to the required formal parameter

This is probably not the best way to be doing this but it's the best I know how to do with c#. I'm trying to create a dictionary and then convert it to json later. Right now I"m just trying to get the dictionary to match what I want in the json format later. Here is what I have so far:
`Dictionary<Dictionary<string, string>, Dictionary<string, List<List<Decimal>>>> testDict = new Dictionary<Dictionary<string, string>, Dictionary<string, List<List<Decimal>>>>() {
new Dictionary<string, string>() {
{ "test", "test" }
}
};`
This is giving me the following error:
There is no argument that corresponds to the required formal parameter
I don't know what could be causing this and any help would be great, thanks!
Here is the json structure I'm trying to replicate:
[
{
"target": "1",
"datapoints": [
[
67.0,
1491609600.0
]
]
},
{
"target": "2",
"datapoints": [
[
54.0,
1491091200.0
],
[
65.0,
1491177600.0
],
[
69.0,
1491609600.0
],
[
65.0,
1491696000.0
],
[
54.0,
1491868800.0
],
[
63.0,
1491955200.0
],
[
64.0,
1492214400.0
],
[
57.0,
1492732800.0
],
[
72.0,
1492819200.0
],
[
50.0,
1493337600.0
],
[
63.0,
1493424000.0
]
]
},
]
Ok, not the answer to your question, but it will help, is the correct structure for your JSON:
public class TargetClass
{
public string target{ get; set; }
public List<double[]> datapoints{ get; set; }
}
That's the base class. If you want to deserialize what you have in JSON you will do something like this (assuming you are using Newtonsoft Json, else change to the library you use):
var data = Newtonsoft.Json.JsonConvert.DeserializeObject<TargetClass[]>(theString);
And to serialize you would create something like this:
var items = new List<TargetClass>();
var target = new TargetClass{ target = "1", datapoints = new List<double[]>{ new double[]{ 67.0, 1491609600.0 } };
items.Add(target);
var ser = Newtonsoft.Json.JsonConvert.SerializeObject(items);
Using anonymous types you can create complex object hierarchies almost as easy as writing plain JSON:
var obj = new[] {
new {
target = "1",
datapoints = new [] {
new [] {
67.0,
1491609600.0
}
}
},
new {
target = "2",
datapoints = new [] {
new [] {
54.0,
1491091200.0
},
new [] {
65.0,
1491177600.0
},
}
}
};
var json = JsonConvert.SerializeObject(obj, Formatting.Indented);
Demo: https://dotnetfiddle.net/jk8gho
If subcollections in this object are a subject to expansion, these collections should better be explicitly defined as List<dynamic>. Strictly speaking this dynamic is not necessary and explicit types may be used instead, but using dynamic simplifies the definition.
var obj = new List<dynamic> {
new {
target = "1",
datapoints = new List<dynamic> {
new [] {
67.0,
1491609600.0
}
}
},
new {
target = "2",
datapoints = new List<dynamic> {
new [] {
54.0,
1491091200.0
},
new [] {
65.0,
1491177600.0
},
}
}
};
var target2 = obj.Where(t => t.target == "2").Single();
target2.datapoints.Add(new [] {
64.0,
1492214400.0
});
target2.datapoints.Add(new[] {
57.0,
1492732800.0
});
var target3 = new {
target = "3",
datapoints = new List<dynamic> { }
};
target3.datapoints.Add(new[] {
72.0,
1492819200.0
});
obj.Add(target3);
var json = JsonConvert.SerializeObject(obj, Formatting.Indented);
Demo: https://dotnetfiddle.net/d4ZUH8

Deserialize JSON to an array of objects, instead of to one object list

Apologies for the probably confusing title. I'm new to JSON and I'm working on a Web Application with a piece of software which interfaces with the API. I have control of both.
My applications needs to enumerate a list of "Clients" and their "Projects". Currently it returns the following:
{
"clients": [
{
"client_id": "1",
"client_name": "Client1",
"projects": [
{
"client_project_id": "1",
"client_project_title": "WidgetsA",
"client_project_client": "1",
"client_project_status": "1"
},
{
"client_project_id": "11",
"client_project_title": "WidgetsB",
"client_project_client": "1",
"client_project_status": "1"
}
]
},
{
"client_id": "11",
"client_name": "Client11",
"projects": [
{
"client_project_id": "31",
"client_project_title": "Install",
"client_project_client": "11",
"client_project_status": "1"
}
]
},
{
"client_id": "21",
"client_name": "Client21",
"projects": [
{
"client_project_id": "61",
"client_project_title": "Marketing",
"client_project_client": "21",
"client_project_status": "1"
}
]
},
{
"client_id": "31",
"client_name": "Client31",
"projects": [
{
"client_project_id": "71",
"client_project_title": "Fire Everyone",
"client_project_client": "31",
"client_project_status": "1"
},
{
"client_project_id": "81",
"client_project_title": "Buy A Company",
"client_project_client": "31",
"client_project_status": "1"
}
]
}
]
}
I can deserialize this easily enough to an object using the following JSON.NET code:
MyObject result = JsonConvert.DeserializeObject<MyObject>(response);
However, this only works if my objects look like the following:
[Serializable, JsonObject]
internal class MyObject
{
[JsonProperty("clients")]
internal List<ClientObject> ClientList = new List<ClientList>();
}
internal class ClientObject
{
[JsonProperty("client_id")]internal string ClientID { get; set; }
[JsonProperty("client_name")] internal string ClientName { get; set; }
[JsonProperty("projects")] internal List<ProjectObject> ProjectList = new List<ProjectObject>();
}
(NB: I've changed the names of a lot of properties and objects for privacy, so apologies for any mistakes added)
What I really want to be able to do is use the following code:
List<ClientObject> result = JsonConvert.DeserializeObject<List<ClientObject>>(response);
But no matter how I format the JSON response, JSON.NET throws an error stating that the JSON is not an array. Can anyone advise where I'm going wrong, or what I'm misunderstanding?
As others have mentioned, your JSON is an object, not array, so it cannot be deserialized directly to a list.
But you can still use LINQ to JSON to get your clients list from JSON:
string json = #"...";
JObject data = JObject.Parse(json);
List<ClientObject> clients = data["clients"].Select(c => c.ToObject<ClientObject>()).ToList();
Your JSON is an object, that contains a field that is an array. You cannot directly convert it to array.
You can use this JSON I suppose:
[
{
"client_id": "1",
},
{
"client_id": "2",
}
]
But seriously, it does not hurt to have a proper response object that contains an array inside. I would rather us it.

c# NewtonJson Jarray check null/empty error

How we can check a json array is null or emty?
Json:
{
"productList": [
{
"id": 2440,
"serviceStatus": 1,
"listOfBillProductsExtras": [
{
"id": 2441,
"amount": 1,
"balance": 2,
}
],
"deskName": "Desk 1",
"onlyTime": "15:25"
},
{
"id": 2441,
"serviceStatus": 1,
"listOfBillProductsExtras": [ ],
"deskName": "Desk2",
"onlyTime": "15:27"
}
]
}
I try
JArray productList = JArray.Parse(content["productList"].ToString());
but it didn't work. (There was exp. Null Referance ) So, I want to check listOfBillProductsExtras array is null or empty. If not empty I will get the id, amount, balance.
Parse the Json object to jArray:
public ActionResult Method(object[] data)
{
var productList = Json.ParseJsonObjectToJArray(data, "productList");
if(jArray.Count > 0)
{
}
}
public class Json
{
public static JArray ParseJsonObjectToJArray(object[] data, string objectName)
{
dynamic jObject = JObject.Parse(data[0].ToString());
var info = jObject[objectName];
return info;
}
}
This should work
var found = JObject.Parse(json).SelectToken("productList[0].listOfBillProductsExtras[0].id");
where json is your input string.
found variable can be checked for null value.

How can I merge two JObject? [duplicate]

This question already has answers here:
Merge two Json.NET arrays by concatenating contained elements
(3 answers)
Closed 7 years ago.
I have a first json:
{
"data": [{
"id": "id1",
"field": "field1"
}],
"paging": {
"prev": "link1",
}
}
and a second one:
{
"data": [{
"id": "id2",
"field": "field2"
}],
"paging": {
"prev": "link2",
}
}
and I want to merge/union the two Data array, such as:
{
"data": [{
"id": "id1",
"field": "field1"
},
{
"id": "id2",
"field": "field2"
}]
}
(I don't care about about paging right now).
How can I do it quick and easy? This is my try:
var final = JsonConvert.SerializeObject(new { data = json1["data"].Union(json2["data"]) }, Newtonsoft.Json.Formatting.Indented).ToString();
but an Exception is raised: 'Newtonsoft.Json.Linq.JArray' does not contains a definition of 'Union'
Newtonsoft.Json now supports merging objects (old link):
var dataObject1 = JObject.Parse(#"{
""data"": [{
""id"": ""id1"",
""field"": ""field1""
}],
""paging"": {
""prev"": ""link1"",
}
}");
var dataObject2 = JObject.Parse(#"{
""data"": [{
""id"": ""id2"",
""field"": ""field2""
}],
""paging"": {
""prev"": ""link2"",
}
}");
var mergeSettings = new JsonMergeSettings
{
MergeArrayHandling = MergeArrayHandling.Union
};
// method 1
(dataObject1.SelectToken("data") as JArray).Merge(dataObject2.SelectToken("data"), mergeSettings);
// method 2
//dataObject1.Merge(dataObject2, mergeSettings);
var mergedArray = dataObject1.SelectToken("data") as JArray;
Console.WriteLine(mergedArray.ToString(Formatting.None));
(checked with brain-compiler ;) )
JArray dataOfJson1=json1.SelectToken("data");
JArray dataofJson2=json2.SelectToken("data");
foreach(JObject innerData in dataofJson2)
{
dataOfJson1.Add(innerData);
}
For those that (like me) cannot use the new JSON.net library.
The following method is what I use.
public static JObject mergeJsonObjects(List<JObject> objects) {
JObject json = new JObject();
foreach(JObject JSONObject in objects) {
foreach(var property in JSONObject) {
string name = property.Key;
JToken value = property.Value;
json.Add(property.Key, property.Value);
}
}
return json;
}
The method takes an list of JObjects and returns a single JObject, simpel and effective.
A possible solution could be:
class Container
{
public List<IdField> data{get;set;}
}
class IdField
{
public string id{get;set;}
public string field{get;set;}
}
string s1 = "{ \"data\": [{ \"id\": \"id1\", \"field\": \"field1\" }], \"paging\": { \"prev\": \"link1\", } }";
string s2 = "{ \"data\": [{ \"id\": \"id2\", \"field\": \"field2\" }], \"paging\": { \"prev\": \"link2\", } }";
var d1 = JsonConvert.DeserializeObject<Container>(s1);
var d2 = JsonConvert.DeserializeObject<Container>(s2);
d1.data.AddRange(d2.data);
var result = JsonConvert.SerializeObject(d1);

Categories