Jason Higgins
Jason Higgins

Reputation: 1526

Deserializing JSON with dynamic keys

I'm quite new to JSON, and am currently learning about (de)serialization. I'm retrieving a JSON string from a webpage and trying to deserialize it into an object. Problem is, the root json key is static, but the underlying keys are dynamic and I cannot anticipate them to deserialize. Here is a mini example of the string :

{
    "daily": {
        "1337990400000": 443447,
        "1338076800000": 444693,
        "1338163200000": 452282,
        "1338249600000": 462189,
        "1338336000000": 466626
    }
}

For another JSON string in my application, I was using a JavascriptSerializer and anticipating the keys using class structure. What's the best way to go about deserializing this string into an object?

Upvotes: 17

Views: 30302

Answers (5)

Greg Gum
Greg Gum

Reputation: 37909

Here is a concrete example:

{
    "translation": {
        "el": {
            "name": "Greek",
            "nativeName": "Ελληνικά",
            "dir": "ltr"
        },
        "en": {
            "name": "English",
            "nativeName": "English",
            "dir": "ltr"
        }
    }
}
var dictionary = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, Dictionary<string,string>>>>(json);
//There is only one top level item, so get that here.
var languages = dictionary["translation"];
List<LanguageInfo> languageInfos = new List<LanguageInfo>();

foreach (var language in languages) {
    var newLanguageInfo = new LanguageInfo();
    newLanguageInfo.LanguageId = language.Key;
    newLanguageInfo.EnglishName = language.Value["name"];
    newLanguageInfo.NativeName = language.Value["nativeName"];
    newLanguageInfo.Direction = language.Value["dir"];
    languageInfos.Add(newLanguageInfo);
}
public class LanguageInfo
 {
     public string LanguageId { get; set; }
     public string EnglishName { get; set; }
     public string NativeName { get; set; }
     public string Direction { get; set; }

 }

Upvotes: 0

haldo
haldo

Reputation: 16701

Whenever you have JSON with dynamic keys it can usually be deserialized into a Dictionary<string, SomeObject>. Since the inner JSON keys are dynamic (in this question) the JSON can be modelled as:

Dictionary<string, Dictionary<string, int>>

I would recommend using NewtonSoft.Json (JSON.Net) or System.Text.Json (if you're working in .NET-Core 3.0 and up).

Newtonsoft.Json

Use DeserializeObject<T> from JsonConvert:

var response = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, int>>>(json);

System.Text.Json

Use Deserialize<T> from JsonSerializer:

var response = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, int>>>(json);

Upvotes: 6

Rawling
Rawling

Reputation: 50114

Seriously, no need to go down the dynamic route; use

var deser = new JavaScriptSerializer()
    .Deserialize<Dictionary<string, Dictionary<string, int>>>(val);
var justDaily = deser["daily"];

to get a dictionary, and then you can e.g.

foreach (string key in justDaily.Keys)
    Console.WriteLine(key + ": " + justDaily[key]);

to get the keys present and the corresponding values.

Upvotes: 37

Boris Gappov
Boris Gappov

Reputation: 2493

This is not convenient to use, because in с# can not be defined a variable starts with a number. Add prefix to keys.

Or try this:

string json = "
{ daily:[
  { key: '1337990400000', val:443447 },
  { key: '1338076800000', val:444693 },
  { key: '1338163200000', val:452282 },
  { key: '1338249600000', val:462189 },
  { key: '1338336000000', val:466626 }]
}";

public class itemClass
{
  public string key; // or int
  public int val;
}

public class items
{
  public itemClass[] daily;
}

items daily = (new JavascriptSerializer()).Deserialize<items>(json);

Then you can:

var itemValue = items.Where(x=>x.key=='1338163200000').Select(x=>x.val).FirstOrDefault();

Upvotes: -2

Lloyd
Lloyd

Reputation: 29668

You can use dynamic in .NET 4 or later. For example with JSON.NET I can do:

dynamic obj = JsonConvert.Deserialize<dynamic>("{x: 'hello'}");

You can then do:

var str = obj.x;

However, unsure how it will handle numeric keys. You can of course just use JObject directly itself, for example:

var obj = JObject.Parse("{'123456': 'help'}");
var str = obj["123456"];

Upvotes: 5

Related Questions