Tony Tony - 5 months ago 60
JSON Question

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.

Answer

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

Comments