Question

Given Json input like the following:

{
    "Group A": {
        "Prop A": 42,
        "Prop B": true,
        "Prop C": [ "Hello", "World!" ]
    },
    "Group B": {
        "Prop A": 72
    }
}

I would like to populate the following data structure:

Dictionary<string, Dictionary<string, string>> Groups;

Such that the following statement would be true (differences in whitespace are not important):

Groups["Group A"]["Prop C"] == "[\"Hello\",\"World!\"]"

Inefficient Solution:

The following seems to solve this problem, but it is quite inefficient since it incurs unnecessary intermediary serialization:

Groups = new Dictionary<string, Dictionary<string, string>>();
foreach (var jsonGroup in JObject.Parse(jsonText)) {
    var group = new Dictionary<string, string>();
    Groups[jsonGroup.Key] = group;

    foreach (var jsonProperty in jsonGroup.Value.Children<JProperty>())
        group[jsonProperty.Name] = JsonConvert.SerializeObject(jsonProperty.Value);
}

Sadly JProperty.Value.ToString() seems to return odd values, for instance "False" instead of "false".

Was it helpful?

Solution

It seems that the intended behaviour of JValue.ToString() is to return the enclosed value as a string rather than encode to JSON. Instead JValue.ToString(IFormatProvider) should be used to produce a valid JSON encoded string.

https://github.com/JamesNK/Newtonsoft.Json/issues/266

However, in my particular case it seems to make better sense to retain the Json.NET representation since this avoids reparsing the same JSON content multiple times:

Groups = new Dictionary<string, Dictionary<string, JToken>>();
foreach (var jsonGroup in JObject.Parse(jsonText)) {
    var group = new Dictionary<string, JToken>();
    Groups[jsonGroup.Key] = group;

    foreach (var jsonProperty in jsonGroup.Value.Children<JProperty>())
        group[jsonProperty.Name] = jsonProperty.Value;
}

And then, instead of parsing these sub-structures with JObject.Parse I can use JToken.ToObject<T> to convert them into the desired representation:

bool myValue = Groups["Group A"]["Prop B"].ToObject<bool>();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top