How to parse this JSON using Newton Soft for neste

2019-09-25 08:10发布

问题:

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);

回答1:

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; }
}


回答2:

@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.