user0404
user0404

Reputation: 113

Looping through JSON array's object

I have a JSON string like below

 {"data":[{"report_header":{"c1":{"name":"COLUMN1","type":"java.lang.String"},"c2":{"name":"COLUMN2","type":"java.lang.String"}},"report_row":[{"c1":"2019","c2":"TEST123"},{"c1":"2019","c2":"TEST345"},{"c1":"2020","c2":"TEST567"}]}],"message":["OK"],"status":200}

I have used json2csharp and created classes.

    public class C1
{
    public string name { get; set; }
    public string type { get; set; }
}

public class C2
{
    public string name { get; set; }
    public string type { get; set; }
}

public class ReportHeader
{
    public C1 c1 { get; set; }
    public C2 c2 { get; set; }
}

public class ReportRow
{
    public string c1 { get; set; }
    public string c2 { get; set; }
}

public class Datum
{
    public ReportHeader report_header { get; set; }
    public List<ReportRow> report_row { get; set; }
}

public class RootObject
{
    public List<Datum> data { get; set; }
    public List<string> message { get; set; }
    public int status { get; set; }
}

And reading values using below code

var jss = new JavaScriptSerializer();
var ListExample = jss.Deserialize<RootObject>(result);
IList<Datum> listData = ListExample.data;
IList<ReportRow> reportRows = listData[0].report_row;

foreach (ReportRow row in reportRows)
                {

                    Console.WriteLine(row.c1.ToString());
                    Console.WriteLine(row.c2.ToString());

                }

My question is how I can modify above code to make it more generic so that in can handle more columns. Like what if I have more columns like c3,c4 in Jason. How can I iterate through them without re-writing Report Row class for all such use cases.

Upvotes: 2

Views: 5567

Answers (2)

Pavel Anikhouski
Pavel Anikhouski

Reputation: 23298

You can easily access all properties inside report_row item using Newtonsoft.Json.Linq, by iterating through data array items, and then iterating through every report_row

var obj = JObject.Parse(json);
foreach (var dataItem in obj["data"])
{
    foreach (var row in dataItem["report_row"])
    {
        var c1 = row["c1"].Value<int>();
        var c2 = row["c2"].Value<string>();
        //var c3 = ...
    }
}       

Another option is to deserialize a json into IDictionary<string,object> using Deserialize method of JavaScriptSerializer, and then access dictionary keys and values

var serializer = new JavaScriptSerializer();
var result = serializer.Deserialize<IDictionary<string,object>>(json);

But using JavaScriptSerializer class is not recommended

Upvotes: 2

aloisdg
aloisdg

Reputation: 23541

You can use a Dictionary to achieve the expected result without trouble:

var root = JsonConvert.DeserializeObject<RootObject>(result);
var report_row = root.data[0].report_row;
foreach (var reportRow in report_row)
    foreach (var row in reportRow)
        Console.WriteLine(row.Key + ", " + row.Value);

output example:

c1, 2019
c2, TEST123
c3, HERE IS C3
c1, 2019
c2, TEST345
c1, 2020
c2, TEST567

With the following model

public class C1
{
    public string name { get; set; }
    public string type { get; set; }
}

public class C2
{
    public string name { get; set; }
    public string type { get; set; }
}

public class ReportHeader
{
    public C1 c1 { get; set; }
    public C2 c2 { get; set; }
}

public class Datum
{
    public ReportHeader report_header { get; set; }
    public List<Dictionary<string, string>> report_row { get; set; }
}

public class RootObject
{
    public List<Datum> data { get; set; }
    public List<string> message { get; set; }
    public int status { get; set; }
}

Try it online

Edit: Since OP updated the json, here is a outdated demo to try out. The idea of using a Dictionary is exactly the same though.

Upvotes: 1

Related Questions