问题
I am deserializing some nested JSON with the following:
string json = @"{
""name"": ""charlie"",
""someID"": 123,
""level1"" : {
""name"": ""charlie 1"",
""someID"": 456
}
}";
JavaScriptSerializer serializer = new JavaScriptSerializer();
Dictionary<string, object> data = serializer.Deserialize<Dictionary<string, object>>(json);
Once this is done, the values of each dictionary key may be another Dictionary, and so on, multiple levels deep.
What I would like to do is to flatten the multi-level data so it's just a flat Array/List, with just all the JSON attribute names and their values. So that I end up with something like this:
name, "charlie"
someID, 123
name, charlie 1
someID, 456
I was heading down the path of using SelectMany() and so forth, but could not wrangle it to do what I am after.
I've been sort of waddling around with things like this:
var obj = data.Values.SelectMany<object, Dictionary<string, object>>(x => x);
But I am not able to satisfy the compiler. Yes, I am lost.
I am using .NET 3.5.
回答1:
Func<Dictionary<string, object>, IEnumerable<KeyValuePair<string, object>>> flatten = null;
flatten = dict => dict.SelectMany(kv =>
kv.Value is Dictionary<string,object>
? flatten((Dictionary<string,object>)kv.Value)
: new List<KeyValuePair<string,object>>(){ kv}
);
var flatList = flatten(data).ToList();
回答2:
You need recursion here:
IEnumerable<Tuple<string, string>> Flatten(this IDictionary dict)
{
foreach(DictionaryEntry kvp in dict)
{
var childDictionary = kvp.Value as IDictionary;
if(childDictionary != null)
{
foreach(var tuple in childDictionary.Flatten())
yield return tuple;
}
else
yield return Tuple.Create(kvp.Key.ToString(), kvp.Value.ToString());
}
}
// Usage:
var flatList = data.Flatten().ToList();
On .NET 3.5, you can use KeyValuePair<string, string>
instead of Tuple<string, string>
.
Please note that there is no KeyValuePair.Create
, you need to use new KeyValuePair<string, string>(kvp.Key.ToString(), kvp.Value.ToString())
instead.
来源:https://stackoverflow.com/questions/12402670/flatten-nested-dictionarystring-object