Domanda

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".

È stato utile?

Soluzione

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>();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top