Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

json

c#

json.net

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

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

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.

Many thanks

like image 708
Bataleon Avatar asked Nov 08 '12 10:11

Bataleon


1 Answers

One option would be to do something like this (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();
like image 154
nick_w Avatar answered Oct 14 '22 02:10

nick_w