Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the most effective way to parse JSON objects that are dynamically named?

Tags:

json

c#

I'm trying to parse a JSON response that includes something I'm not quite familiar with, nor have I seen in the wild that often.

Inside one of the JSON objects, there is a dynamically named JSON object.

In this example, there is a JSON object inside "bugs" named "12345" which correlates to a bug number.

{
   "bugs" : {
      "12345" : {
         "comments" : [
            {
               "id" : 1,
               "text" : "Description 1"
            },
            {
               "id" : 2,
               "text" : "Description 2"
            }
         ]
      }
   }
}

What I'm curious about is: What would be the most effective way to parse a dynamically-named JSON object like this?

Given some JSON Utility tools like

  • http://jsonutils.com/
  • http://json2csharp.com/

They will take a JSON response like the one above and morph it into classes like the following respectfully:

jsonutils

public class Comment
{
    public int id { get; set; }
    public string text { get; set; }
}

public class 12345
{
    public IList<Comment> comments { get; set; }
}

public class Bugs
{
    public 12345 12345 { get; set; }
}

public class Root
{
    public Bugs bugs { get; set; }
}

json2charp

public class Comment
{
    public int id { get; set; }
    public string text { get; set; }
}

public class __invalid_type__12345
{
    public List<Comment> comments { get; set; }
}

public class Bugs
{
    public __invalid_type__12345 __invalid_name__12345 { get; set; }
}

public class RootObject
{
    public Bugs bugs { get; set; }
}

The problem about this is that it generates a class with a dynamic name. Thus subsequent queries with other identifiers to this API would result in a failure because the name does not match up nor would a generated [JsonProperty("")] as it would contain the dynamic class name as per the generated examples above.

Although the JSON is valid, this seems to be a limitation with JSON that is formatted this way. Unfortunately I do not have any control on this JSON API, so I'm curious what the best way to approach this problem would be?

like image 691
Jon Douglas Avatar asked Jan 09 '17 19:01

Jon Douglas


People also ask

What are the methods to parse JSON?

The JSON. parse() method parses a JSON string, constructing the JavaScript value or object described by the string. An optional reviver function can be provided to perform a transformation on the resulting object before it is returned.

What is a dynamic JSON?

A dynamic JSON file will be created to store the array of JSON objects. Consider, we have a database named gfg, a table named userdata. Now, here is the PHP code to fetch data from database and store them into JSON file named gfgfuserdetails. json by converting them into an array of JSON objects.

How efficient is JSON parse?

Parsing JSON is much more efficient than parsing object literals in JavaScript. This is true across all major JavaScript execution engines by up to 2x for an 8MB file, as demonstrated by this parsing benchmark.


2 Answers

Try Json.NET, available as a Nuget package (Newtonsoft.Json) or from http://www.newtonsoft.com/json.

Json.NET can perform class-based serialization/deserialization such as you show. It also provides a generic JObject and JToken classes for cases where the format of the Json is not known or not fixed at dev time.

Here's an example loading a json object from a file.

// load file into a JObject
JObject document;
using (var fileStream = File.OpenRead(someFilePath))
using (var streamReader = new StreamReader(fileStream))
using (var jsonReader = new JsonTextReader(streamReader))
    document = JObject.Load(jsonReader);

// read the JObject
var bugs = (JObject) document["bugs"];
foreach (var bugEntry in bugs)
{
    var bugID = bugEntry.Key;
    var bugData = (JObject) bugEntry.Value;
    var comments = (JArray) bugData["comments"];
    foreach (JObject comment in comments)
        Debug.Print(comment["text"]);
}
like image 146
Michael Gunter Avatar answered Oct 08 '22 08:10

Michael Gunter


Newtonsoft.Json JsonConvert can parse it as a Dictionary<String, Comments> provided with appropriate model classes:

public class Comment
{
    public int id { get; set; }
    public string text { get; set; }
}

public class Comments
{
    public List<Comment> comments { get; set; }
}

public class RootObject
{
    public Dictionary<String, Comments> bugs { get; set; }
}

That can be checked with:

var json = "{\r\n   \"bugs\" : {\r\n      \"12345\" : {\r\n         \"comments\" : [\r\n            {\r\n               \"id\" : 1,\r\n               \"text\" : \"Description 1\"\r\n            },\r\n            {\r\n               \"id\" : 2,\r\n               \"text\" : \"Description 2\"\r\n            }\r\n         ]\r\n      }\r\n   }\r\n}";

Console.WriteLine(json);

var obj = JsonConvert.DeserializeObject<RootObject>(json);

Console.WriteLine(obj.bugs["12345"].comments.First().text);
like image 42
Eugene Podskal Avatar answered Oct 08 '22 08:10

Eugene Podskal