Deserialize nested JSON into C# objects

87,540

Solution 1

For "Items" use a Dictionary<string, List<Info>>, i.e.:

class Response
{
    public Dictionary<string, List<Info>> Items { get; set; }
    public string[] Errors { get; set; }
}

class Info
{
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
    public int Prop3 { get; set; }
    public bool Prop4 { get; set; }
}

This assumes that the item names "Item322A" and "Item2B" will vary from response to response, and reads these names in as the dictionary keys.

Sample fiddle.

Solution 2

Use this this site for representation:

https://quicktype.io/csharp/

something like this may help you

public class Item322A
{
    public string prop1 { get; set; }
    public string prop2 { get; set; }
    public int prop3 { get; set; }
    public bool prop4 { get; set; }
}

public class Item2B
{
    public string prop1 { get; set; }
    public string prop2 { get; set; }
    public int prop3 { get; set; }
    public bool prop4 { get; set; }
}

public class Items
{
    public List<Item322A> Item322A { get; set; }
    public List<Item2B> Item2B { get; set; }
}

public class jsonObject
{
    public Items Items { get; set; }
    public List<string> Errors { get; set; }
}

Here is how to deserialize (use JsonConvert class):

jsonObject ourlisting = JsonConvert.DeserializeObject<jsonObject>(strJSON);

Solution 3

You could use Json.Parse so that you can query into the data -- and just use the single model.

private class Info
{
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
    public int Prop3 { get; set; }
    public bool Prop4 { get; set; }
}

var result = JObject.Parse(resultContent);   //parses entire stream into JObject, from which you can use to query the bits you need.
var items = result["Items"].Children().ToList();   //Get the sections you need and save as enumerable (will be in the form of JTokens)

List<Info> infoList = new List<Info>();  //init new list to store the objects.

//iterate through the list and match to an object. If Property names don't match -- you could also map the properties individually. Also useful if you need to dig out nested properties.
foreach(var subItem in items){
foreach(JToken result in subItem){
Info info = result.ToObject<Info>();
infoList.add(info);
}}
Share:
87,540

Related videos on Youtube

user3574076
Author by

user3574076

please delete me

Updated on May 10, 2020

Comments

  • user3574076
    user3574076 about 4 years

    I am getting JSON back from an API that looks like this:

    {
      "Items": {
        "Item322A": [{
          "prop1": "string",
          "prop2": "string",
          "prop3": 1,
          "prop4": false
        },{
          "prop1": "string",
          "prop2": "string",
          "prop3": 0,
          "prop4": false
        }],
           "Item2B": [{
          "prop1": "string",
          "prop2": "string",
          "prop3": 14,
          "prop4": true
        }]
      },
      "Errors": ["String"]
    }
    

    I have tried a few approaches to represent this JSON in c# objects (too many to list here). I've tried with lists and dictionaries, here is a recent example of how I've tried to represent it:

        private class Response
        {
            public Item Items { get; set; }
            public string[] Errors { get; set; }
        }
    
        private class Item
        {
            public List<SubItem> SubItems { get; set; }
        }
    
        private class SubItem
        {
            public List<Info> Infos { get; set; }
        }
    
        private class Info
        {
            public string Prop1 { get; set; }
            public string Prop2 { get; set; }
            public int Prop3 { get; set; }
            public bool Prop4 { get; set; }
        }
    

    And here is the method I am using to deserialize the JSON:

        using (var sr = new StringReader(responseJSON))
        using (var jr = new JsonTextReader(sr))
        {
            var serial = new JsonSerializer();
            serial.Formatting = Formatting.Indented;
            var obj = serial.Deserialize<Response>(jr);
        }
    

    obj contains Items and Errors. And Items contains SubItems, but SubItems is null. So nothing except for Errors is actually getting deserialized.

    It should be simple, but for some reason I can't figure out the correct object representation

  • user3574076
    user3574076 almost 8 years
    Item322A and Item2B are not constants. But thanks for the answer
  • user3574076
    user3574076 almost 8 years
    Cool, I am going to try this. I just tried a similar approach, but had the Dictionary wrapped up in a list!
  • user3574076
    user3574076 almost 8 years
    This worked. Turns out my last attempt was so close
  • user3574076
    user3574076 about 6 years
    As a follow up to this for anyone interested. If you use visual studio you can use the Paste Special feature. And basically do the same as the linked site in this answer. Also applies for XML