C#flattening json结构

我在C#中有一个json对象(表示为Newtonsoft.Json.Linq.JObject对象),我需要将其展平为字典。 让我举例说明我的意思:

{ "name": "test", "father": { "name": "test2" "age": 13, "dog": { "color": "brown" } } } 

这应该产生一个包含以下键值对的字典:

 ["name"] == "test", ["father.name"] == "test2", ["father.age"] == 13, ["father.dog.color"] == "brown" 

我怎样才能做到这一点?

 JObject jsonObject=JObject.Parse(theJsonString); IEnumerable jTokens = jsonObject.Descendants().Where(p => p.Count() == 0); Dictionary results = jTokens.Aggregate(new Dictionary(), (properties, jToken) => { properties.Add(jToken.Path, jToken.ToString()); return properties; }); 

我有一个将嵌套的json结构展平为字典对象的相同要求。 在这里找到解决方案。

您可以使用https://github.com/jsonfx/jsonfx将json反序列化为动态对象。 然后使用ExpandoObject获取所需内容。

 public Class1() { string json = @"{ ""name"": ""test"", ""father"": { ""name"": ""test2"", ""age"": 13, ""dog"": { ""color"": ""brown"" } } }"; var reader = new JsonFx.Json.JsonReader(); dynamic output = reader.Read(json); Dictionary dict = new Dictionary(); GenerateDictionary((System.Dynamic.ExpandoObject) output, dict, ""); } private void GenerateDictionary(System.Dynamic.ExpandoObject output, Dictionary dict, string parent) { foreach (var v in output) { string key = parent + v.Key; object o = v.Value; if (o.GetType() == typeof(System.Dynamic.ExpandoObject)) { GenerateDictionary((System.Dynamic.ExpandoObject)o, dict, key + "."); } else { if (!dict.ContainsKey(key)) { dict.Add(key, o); } } } } 

我实际上在今天早些时候遇到了同样的问题,最初在SO上找不到这个问题,最后编写了我自己的扩展方法来返回包含JSON blob的叶节点值的JValue对象。 除了一些改进之外,它与接受的答案类似:

  1. 它处理您提供的任何JSON(数组,属性等),而不仅仅是JSON对象。
  2. 减少内存使用量
  3. 在最终不需要的后代上没有调用.Count()

根据您的使用情况,这些可能相关或不相关,但它们适用于我的情况。 我写过关于学习在我的博客上展平JSON.NET对象的文章 。 这是我写的扩展方法:

 public static class JExtensions { public static IEnumerable GetLeafValues(this JToken jToken) { if (jToken is JValue jValue) { yield return jValue; } else if (jToken is JArray jArray) { foreach (var result in GetLeafValuesFromJArray(jArray)) { yield return result; } } else if (jToken is JProperty jProperty) { foreach (var result in GetLeafValuesFromJProperty(jProperty)) { yield return result; } } else if (jToken is JObject jObject) { foreach (var result in GetLeafValuesFromJObject(jObject)) { yield return result; } } } #region Private helpers static IEnumerable GetLeafValuesFromJArray(JArray jArray) { for (var i = 0; i < jArray.Count; i++) { foreach (var result in GetLeafValues(jArray[i])) { yield return result; } } } static IEnumerable GetLeafValuesFromJProperty(JProperty jProperty) { foreach (var result in GetLeafValues(jProperty.Value)) { yield return result; } } static IEnumerable GetLeafValuesFromJObject(JObject jObject) { foreach (var jToken in jObject.Children()) { foreach (var result in GetLeafValues(jToken)) { yield return result; } } } #endregion } 

然后在我的调用代码中,我只是从返回的JValue对象中提取PathValue属性:

 var jToken = JToken.parse("blah blah json here"); foreach (var jValue in jToken.GetLeafValues() { Console.WriteLine("{jValue.Path} = {jValue.Value}"); }