Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserializing JSON using JSon.NET with dynamic data

I'm trying to deserialize some JSON data into objects for an application. Up until now it's been fine because the properties on the JSON data was static (key with a value). Now I've got a result where the key is a dynamic piece of data.

Here's an example JSON url:

http://en.wikipedia.org/w/api.php?action=query&format=json&pageids=6695&prop=info

The resulting JSON for this is:

{ "query" : { "pages" : { "6695" : { "counter" : "",
          "lastrevid" : 468683764,
          "length" : 8899,
          "ns" : 0,
          "pageid" : 6695,
          "title" : "Citadel",
          "touched" : "2012-01-03T19:16:16Z"
        } } } }

Okay, that's great except I can't deserialize the "pages" data into an object. If I were to define a class for the pages it would have to look like this:

public class 6695
{
    public string counter { get; set; }
    public int lastrevid { get; set; }
    public int length { get; set; }
    public int ns { get; set; }
    public int pageid { get; set; }
    public string title { get; set; }
    public string touched { get; set; }
}

In order to deserialze the contents (using JsonConvert.Deserialize(jsondata)) and we all know we can't have a class called 6695. Not only that, the name of the class would have to be different (for example pageid=7145 would have to be the 7145 class).

I can seem to pluck some values out if I use something like JObject.Parse(content) and then access items as JArrays but it's pretty ugly and I'm still stuck on trying to get out the data from the pages array.

Looking for someone to help with this. I don't think it's uncommon, it's just not JSON data I've come across before and not sure how to handle it.

Thanks!

PS forgot to mention this is on Windows Phone 7 so "dynamic" isn't available!

like image 478
Bil Simser Avatar asked Jan 05 '12 05:01

Bil Simser


2 Answers

The simplest method. In this particular case would probably be to go dynamic.

dynamic data = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json);
var lastRevId = data.query.pages["6695"].lastrevid;

You can reference any element by it's [] name so you can do something like data["query"]["pages"]["6695"]["lastrevid"]. This will get by all those little objects where the name isn't valid in c#.

like image 165
Buildstarted Avatar answered Sep 27 '22 20:09

Buildstarted


Here is how you do using https://github.com/facebook-csharp-sdk/simple-json ( https://nuget.org/packages/SimpleJson ).

var text = "{\"query\":{\"pages\":{\"6695\":{\"pageid\":6695,\"ns\":0,\"title\":\"Citadel\",\"touched\":\"2012-01-03T19:16:16Z\",\"lastrevid\":468683764,\"counter\":\"\",\"length\":8899}}}}";

(Using dynamic)

dynamic json = SimpleJson.DeserializeObject(text);
string title = json.query.pages["6695"].title;

foreach (KeyValuePair<string, dynamic> page in json.query.pages)
{
    var id = page.Key;
    var pageId = page.Value.pageid;
    var ns = page.Value.ns;
}

(Using strongly typed classes)

class result
{
    public query query { get; set; }
}
class query
{
    public IDictionary<string, page> pages { get; set; }
}
class page
{
    public long pageid { get; set; }
    public string title { get; set; }
}

var result = SimpleJson.DeserializeObject<result>(text);

[Update]

on windows phone where dynamic is not supported and you don't want to use strongly typed classes.

var json = (IDictionary<string, object>)SimpleJson.DeserializeObject(text);
var query = (IDictionary<string, object>)json["query"];
var pages = (IDictionary<string, object>)query["pages"];
var pageKeys = pages.Keys;
var page = (IDictionary<string, object>)pages["6695"];
var title = (string)page["title"];
like image 29
prabir Avatar answered Sep 27 '22 20:09

prabir