-3

How to parse this JSON

using Newton Soft

I tried but gives me null as my modal should have class 1, 2, 3 ... but that's dynamic .So getting confuse.

Appreciate your help !

{
"data": {
    "1": {
        "test": {
            "col1": "123",
            "col2": "name"
        }
    },
    "2": {
        "test": {
            "col1": "345",
            "col2": "name2"
        }
    },
    "3": {
        "test": {
            "col1": "456",
            "col2": "name3"
        }
    }
}
class root 
{ 
    data data{get; set;};
}

class data
{ 
    List<object> innerObject {get; set;} //not sure as labels are dynamic 
} 

class test
{ 
    col1{get; set;} 
    col2{get; set;} 
} //Calling it in that way .. 

root r = JsonConvert.DeserializeObject<root>(result);
Andrew Whitaker
  • 124,656
  • 32
  • 289
  • 307
  • 2
    Please show your code – Yacoub Massad Jan 22 '16 at 12:44
  • `class root { data data{get; set;}; } class data { List innerObject {get; set;} //not sure as labels are dynamic } class test { col1{get; set;} col2{get; set;} } //Calling it in that way .. root r = JsonConvert.DeserializeObject(result);` in r i will get object of all json I don;t know what should i write in data class so parse the inner node. – Mayank Jhawar Jan 22 '16 at 13:08
  • "data" isn't a json-array. It's an object. So you can't parse it as an array/list. – J. Steen Jan 22 '16 at 13:09
  • @MayankJhawar, can you please [edit](http://stackoverflow.com/posts/34947044/edit) your question to include the code? – Yacoub Massad Jan 22 '16 at 13:11

2 Answers2

0

You can use a dictionary to parse a JSON object with custom property names:

public class Test
{
    public string col1 { get; set; }
    public string col2 { get; set; }
}

public class DataValue
{
    public Test test { get; set; }
}

public class RootObject
{
    public RootObject() { this.data = new Dictionary<string, DataValue>(); }
    public Dictionary<string, DataValue> data { get; set; }
}

See Deserialize a Dictionary.

If you are sure the dictionary keys will always be numeric, you can use integer keys, and use a SortedDictionay to order the values:

public class RootObject
{
    public RootObject() { this.data = new SortedDictionary<long, DataValue>(); }
    public SortedDictionary<long, DataValue> data { get; set; }
}
dbc
  • 104,963
  • 20
  • 228
  • 340
0

@dbc's answer is a good option, but you have a few other options as well:

  1. If you have control over the JSON that's being generated, make your life easier by using an Array if you can. It looks like what you would really want is this:

    {
        "data": [{
            "test": {
                "col1": "123",
                "col2": "name"
            }, {
            "test": {
                "col1": "345",
                "col2": "name2"
            }, /* etc */
        ]
    }
    

    This way, data represents an array and you can deserialize it as such:

    class Root 
    { 
        List<Data> Data  { get; set; };
    }
    
    class Data
    {
        Test Test { get; set; }
    }
    
    JsonConvert.DeserializeObject<Root>(json);
    
  2. You could force your JSON into an array structure using a custom converter. This is making a lot of assumptions about your JSON. For example, it's assuming that you have an object with a integer keys, with no spaces in between numbers:

    public class ObjectAsArrayConverter : JsonConverter 
    {
      public override bool CanConvert(Type type)
      {         
        return
          type.IsGenericType &&
          typeof(List<>) == type.GetGenericTypeDefinition() &&
          typeof(Data) == type.GetGenericArguments()[0];
      }
    
      public override object ReadJson(
        JsonReader reader,
        Type objectType,
        object existingValue,
        JsonSerializer serializer)
      {
        JObject obj = JObject.ReadFrom(reader).ToObject<JObject>();
    
        return obj.Properties()
          .Select(p => new { Index = int.Parse(p.Name), Value = obj[p.Name].ToObject<Data>() })
          .OrderBy(p => p.Index)
          .Select(p => p.Value)
          .ToList();
      }
    
      public override void WriteJson(
        JsonWriter writer,
        object value,
        JsonSerializer serializer)
      {
        throw new NotImplementedException();
      }
    
    }
    

    This would allow you to deserialize your JSON into this structure:

    class Root 
    { 
        public List<Data> Data {get; set;}
    }
    
    class Data
    {
        public Test Test { get; set; }
    }
    
    class Test
    { 
        public string Col1 {get; set;} 
        public string Col2 {get; set;}
    }
    

    Example: https://dotnetfiddle.net/e2Df7h

You might need to tweak the second suggestion, for example if you expect the array to be sparse you might want to make the code expect that.

Community
  • 1
  • 1
Andrew Whitaker
  • 124,656
  • 32
  • 289
  • 307