简体   繁体   中英

JSON to C# — list fields without sub-field names in json?

Using Json.net (Newtonsoft.json), how can I define a C# class (or classes) to handle the json below?

The 'data' field appears to be a list of level/description sub-fields but note they are not preceded by field names.

The 'error' field appears to be a list of error-number/error-message sub-fields but note, they too, are not preceded by field names.

{
  "status": "error",
  "data": [
    {
       "warning" : "your input was wrong"
    }
  ],
  "error": [
    {
      "373": "Error description goes here"
    }
  ]
}

This class definition does not generate parsing errors; however the contents of Data and Errors is not correct.

public class ApiResponse
{
    [JsonProperty(PropertyName = "status")]
    public string Status;

    [JsonProperty(PropertyName = "data")]
    public IEnumerable<KeyValuePair<string, string>> Data;

    [JsonProperty(PropertyName = "error")]
    public IEnumerable<KeyValuePair<int, string>> Errors;
};

// this doesn't throw a parsing exception, but the resulting
// Data and Errors fields are not correctly populated.
var x = JsonConvert.DeserializeObject<ApiResponse>(SampleJson);

Any help would be appreciated, thanks.

Try defining your Data and Errors members as IEnumerables of Dictionaries rather than IEnumerables of KeyValuePairs. (Json.Net expects KeyValuePairs to be represented in JSON as objects with explicit Key and Value properties, which is not what you have there.)

public class ApiResponse
{
    [JsonProperty(PropertyName = "status")]
    public string Status;

    [JsonProperty(PropertyName = "data")]
    public IEnumerable<Dictionary<string, string>> Data;

    [JsonProperty(PropertyName = "error")]
    public IEnumerable<Dictionary<int, string>> Errors;
};

You can then read the data out using a foreach loop with SelectMany :

var x = JsonConvert.DeserializeObject<ApiResponse>(SampleJson);
foreach (var kvp in x.Data.SelectMany(d => d))
{
    Console.WriteLine(kvp.Key + ": " + kvp.Value);
}
foreach (var kvp in x.Errors.SelectMany(d => d))
{
    Console.WriteLine(kvp.Key + ": " + kvp.Value);
}

Fiddle: https://dotnetfiddle.net/KJuAPu

There are few issues with the class you have created. As per the provide JSON, you should be creating your classes similar like following code.

 public class Data
    {
        [JsonProperty(PropertyName = "warning")]
        public string Warning { get; set; }
    }
    public class Error
    {
        [JsonProperty(PropertyName = "373")]
        public string Col_373 { get; set; }
    }

    public class ApiResponse
    {
        [JsonProperty(PropertyName = "status")]
        public string Status { get; set; }
        [JsonProperty(PropertyName = "data")]
        public List<Data> Data { get; set; }
        [JsonProperty(PropertyName = "error")]
        public List<Error> Error { get; set; }
    }

Once you have designed the structure like this, you can always get it back to your object structure as following code snippet. It seems, you are getting confused with the property names and values.

 string json = "{\"status\":\"error\", \"data\": [{\"warning\" : \"your input was wrong\" }],  \"error\": [{\"373\": \"Error description goes here\"}]}";

 var res = JsonConvert.DeserializeObject<ApiResponse>(json);

One more observation.

"373" : "Error description goes here"

Please don't use number as the key/column name.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM