2

An existing JSON-based web-service returns a fairly messy JSON object, where all the useful data is contained in the elements of an array which is itself the content of a 1-element array. Something like this (I'm anonymising it, hopefully no typos):

{"rows":[[
    {"name":"John","time":"2016-03-20 01:00:00","id":"2","code":"1234"},
    {"name":"Sam","time":"2016-03-20 01:00:00","id":"24","code":"999"},
    {"name":"Paul","time":"2016-03-20 01:00:00","id":"12","code":"6512"}
]]}

Using JSON.net I need to access each of those row sub-elements but I'm not sure how to iterate over this and if I should be deserializing to a concrete type or just reading the raw data from my json object.

The data will be aggregated inside a method so the 'type' of each row is not something that needs to be known outside the method.

rows will always be a 1-element array containing an array of elements as shown.

2 Answers 2

2

@Fals's solution should work well, but if you want to do away with the RootObject, you can use Json.Net's LINQ-to-JSON API to parse the JSON and get the data into a simple list of items that is easy to work with.

Assuming you have a class defined for the item data like this:

public class Item
{
    public string name { get; set; }
    public DateTime time { get; set; }
    public string id { get; set; }
    public string code { get; set; }
}

Then you can do this to get your list of items:

List<Item> items = JObject.Parse(json)["rows"][0]
                          .Select(jt => jt.ToObject<Item>())
                          .ToList();

Fiddle: https://dotnetfiddle.net/FtB3Cu


If you want to avoid declaring any classes at all and instead use an anonymous type, you can change the code to this:

var items = JObject.Parse(json)["rows"][0]
                   .Select(jt => new 
                   {
                       name = (string)jt["name"],
                       time = (DateTime)jt["time"],
                       id = (string)jt["id"],
                       code = (string)jt["code"]
                   })
                   .ToList();

Fiddle: https://dotnetfiddle.net/0QXUzZ

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Brian. Is there any way you can further combine this with a method-local anonymous type to avoid declaring a concrete type? Or does one simply have a private inner class?
@Mr.Boy Yes, you can use anonymous types. I've edited my answer to show how. It should also work with an inner class if you choose to go that route.
Glad I could help.
1

It's simple, your root object contains a List<List<>>:

Your object should look like:

public class InnerObject
{
    public string name { get; set; }
    public DateTime time { get; set; }
    public string id { get; set; }
    public string code { get; set; }
}

public class RootObject
{
    public List<List<InnerObject>> rows { get; set; }
}

Then use JSON.NET:

string json = @"{'rows':[[
                    {'name':'John','time':'2016-03-20 01:00:00','id':'2','code':'1234'},
                    {'name':'Sam','time':'2016-03-20 01:00:00','id':'24','code':'999'},
                    {'name':'Paul','time':'2016-03-20 01:00:00','id':'12','code':'6512'}
                ]]}";

var rootObject = JsonConvert.DeserializeObject<RootObject>(json);

By the way, this site json2csharp can generate the C# class from JSON, makes the life ease :)

EDIT:

You can also use dynamic, and then avoid the parser from the `RootObject:

var rootObject = JsonConvert.DeserializeObject<dynamic>(json);
rootObject.rows[0] <--- should have what you need

3 Comments

Thanks. Is there a neat way to avoid needing RootObject without having to manually hack the string? e..g just get an array/List of InnerObject back from a JSON.net call?
@Mr.Boy You can create a custom JsonCreationConverter, newtonsoft.com/json/help/html/…
@Mr.Boy see the edit above, makes thinks more dynamic :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.