Search code examples
c#jsonjson.net

Using [JsonProperty] to match JSON parameters to C# class properties which are type List


I'm trying to deserialize the following JSON response (using Json.NET):

[
  {
    "0": "Yes",
    "1": "No",
    "pollid": "1",
    "question": "This is a test",
    "start": "2011-06-28",
    "end": "2012-03-21",
    "category": "Roads"
  }
]

...

Into objects of this type:

class Poll
{
    [JsonProperty("pollid")]
    public int pollid { get; set; }
    [JsonProperty("question")]
    public string question { get; set; }
    [JsonProperty("start")]
    public DateTime start { get; set; }
    [JsonProperty("end")]
    public DateTime end { get; set; }
    [JsonProperty("category")]
    public string category { get; set; }

    // PROBLEM AREA
    [JsonProperty("0")] // Json parameter names are 0 to 9. How can I 'match' these to the List elements?
    public List<string> polloptions { get; set; }
}

How would I use the [JsonProperty] attribute when creating a List? (Assuming the JSON parameter names to be contained in this List are "0" to "9"). I've spent the last few hours trying different methods without any luck.


Solution

  • One option would be to do something like this with Linq (I took the [JsonProperty("0")] off polloptions first):

    int option;
    Poll poll = JsonConvert.DeserializeObject<Poll>(json);
    JContainer container = (JContainer)JsonConvert.DeserializeObject(json);
    
    poll.polloptions = container.Where(t => t as JProperty != null)
        .Cast<JProperty>().Where(p => int.TryParse(p.Name, out option))
        .Select(p => p.Value.Value<string>()).ToList();
    

    The first step is to deserialize as per normal - this will take care of every property except for polloptions. The next step is to deserialize to a JContainer so that we can get at the individual tokens and create a list out of the ones with numeric names (hence the int.TryParse(p.Name, out option)).

    What this will give you as a list populated with the yes/no values. If you would also like the names of the poll options as well as the values, consider this:

    Change the polloptions property to:

    public List<PollOption> polloptions { get; set; }
    

    Where PollOption is:

    class PollOption
    {
        public int Name { get; set; }
        public string Value { get; set; }
    }
    

    When deserializing:

    Poll poll = JsonConvert.DeserializeObject<Poll>(json);
    JContainer container = (JContainer)JsonConvert.DeserializeObject(json);
    
    var pollOptionNames = container.Where(t => t as JProperty != null)
        .Cast<JProperty>().Where(p => int.TryParse(p.Name, out option))
        .Select(p => int.Parse(p.Name)).ToList();
    
    var pollOptionValues = container.Where(t => t as JProperty != null)
        .Cast<JProperty>().Where(p => int.TryParse(p.Name, out option))
        .Select(p => p.Value.Value<string>()).ToList();
    
    poll.polloptions = pollOptionNames.Select((n, i) =>
        new PollOption() { Name = n, Value = pollOptionValues[i] }).ToList();