C#将嵌套JSON转为扁平Dictionary<string,string>求助(Newtonsoft.Json无效)
解决JSON扁平化为Dictionary<string, string>的方案
别担心,Newtonsoft.Json(Json.NET)完全可以实现这个需求——只是需要我们基于它的LINQ to JSON API自己写递归遍历的逻辑来生成扁平键。下面是完整的实现步骤和代码:
核心实现思路
我们需要递归遍历JSON的每个节点,同时记录当前节点的路径(比如Data[0].UserInformation.City这种格式),最后将所有叶子节点的键值对整理到字典中。具体分三种情况处理:
- JObject(JSON对象):遍历每个属性,拼接属性名到路径后递归处理属性值
- JArray(JSON数组):遍历每个元素,用
[索引]的格式拼接路径后递归处理元素 - JValue(JSON值类型):将当前路径作为键,值转为字符串存入字典
完整代码实现
using Newtonsoft.Json.Linq; using System.Collections.Generic; public static class JsonFlattener { public static Dictionary<string, string> FlattenJson(JToken token, string currentPath = "") { var result = new Dictionary<string, string>(); switch (token.Type) { case JTokenType.Object: foreach (JProperty property in token.Children<JProperty>()) { string newPath = string.IsNullOrEmpty(currentPath) ? property.Name : $"{currentPath}.{property.Name}"; result.AddRange(FlattenJson(property.Value, newPath)); } break; case JTokenType.Array: int index = 0; foreach (JToken item in token.Children()) { string newPath = $"{currentPath}[{index}]"; result.AddRange(FlattenJson(item, newPath)); index++; } break; case JTokenType.Integer: case JTokenType.Float: case JTokenType.String: case JTokenType.Boolean: case JTokenType.Null: if (!string.IsNullOrEmpty(currentPath)) { result.Add(currentPath, token.ToString()); } break; } return result; } // 扩展方法:方便合并两个字典 private static void AddRange<TKey, TValue>(this Dictionary<TKey, TValue> target, Dictionary<TKey, TValue> source) { foreach (var pair in source) { target.Add(pair.Key, pair.Value); } } }
测试你的JSON数据
注意你的原始JSON里有个小语法错误:"country:"应该是"country"(多了个冒号),修正后我们来测试:
using System; using Newtonsoft.Json.Linq; class Program { static void Main() { string json = @" { ""Name"" : ""Value1"", ""Data"": [ { ""UserName"": ""test"", ""email"": ""test@test.com"", ""UserInformation"": { ""City"": ""city"", ""country"": ""country"" } }, { ""UserName"": ""test1"", ""email"": ""test1@test.com"" } ] }"; JToken root = JToken.Parse(json); var flatDict = JsonFlattener.FlattenJson(root); // 输出结果验证 foreach (var pair in flatDict) { Console.WriteLine($"""{pair.Key}"" : ""{pair.Value}"""); } } }
运行这段代码后,你会得到完全符合需求的扁平字典:
"Name" : "Value1" "Data[0].UserName" : "test" "Data[0].email" : "test@test.com" "Data[0].UserInformation.City" : "city" "Data[0].UserInformation.country" : "country" "Data[1].UserName" : "test1" "Data[1].email" : "test1@test.com"
关键细节说明
- 扩展方法
AddRange是为了方便递归时合并子字典的结果 - 我们只处理了常见的JSON值类型(整数、浮点数、字符串、布尔、null),如果你的JSON有其他类型(比如日期),可以在
JTokenType的case里补充处理 - 路径拼接逻辑严格按照你要求的格式:数组用
[索引],对象属性用.连接
内容的提问来源于stack exchange,提问作者Max Melnikov
相关产品推荐
相关产品推荐

