如何在C#中递归将JSON转换为类似Python的列表与字典
在C#中递归将JSON转换为类Python的列表与字典结构
刚好做过类似的需求,其实核心就是利用C#的Dictionary<string, object>和List<object>来模拟Python里的dict和list,通过递归遍历JSON的每一个节点,把对应类型转成C#里的动态容器。下面我一步步给你实现:
思路梳理
JSON的结构无非三种:
- 对象(Object):对应Python的dict → C#用
Dictionary<string, object> - 数组(Array):对应Python的list → C#用
List<object> - 基础类型:字符串、数字、布尔、null → 直接转成C#对应的值类型/引用类型
递归的逻辑很简单:遇到对象就遍历键值对,递归处理每个值;遇到数组就遍历每个元素,递归处理每个元素;基础类型直接返回。
实现代码(使用官方System.Text.Json)
首先确保你引用了System.Text.Json(.NET Core 3.0+默认自带,低版本需要安装对应NuGet包),然后写一个递归转换的工具类:
using System; using System.Collections.Generic; using System.Text.Json; public static class JsonConverterUtils { /// <summary> /// 将JsonElement递归转换为类Python的Dictionary/List结构 /// </summary> public static object ConvertToPythonLikeStructure(JsonElement element) { return element.ValueKind switch { JsonValueKind.Object => ConvertObject(element), JsonValueKind.Array => ConvertArray(element), JsonValueKind.String => element.GetString(), JsonValueKind.Number => GetNumberValue(element), JsonValueKind.True => true, JsonValueKind.False => false, JsonValueKind.Null => null, _ => throw new NotSupportedException($"不支持的JSON类型:{element.ValueKind}") }; } /// <summary> /// 转换JSON对象为Dictionary<string, object> /// </summary> private static Dictionary<string, object> ConvertObject(JsonElement element) { var dict = new Dictionary<string, object>(); foreach (var property in element.EnumerateObject()) { dict.Add(property.Name, ConvertToPythonLikeStructure(property.Value)); } return dict; } /// <summary> /// 转换JSON数组为List<object> /// </summary> private static List<object> ConvertArray(JsonElement element) { var list = new List<object>(); foreach (var item in element.EnumerateArray()) { list.Add(ConvertToPythonLikeStructure(item)); } return list; } /// <summary> /// 处理JSON数字类型(兼容int、long、double等) /// </summary> private static object GetNumberValue(JsonElement element) { if (element.TryGetInt64(out long longValue)) return longValue; if (element.TryGetDouble(out double doubleValue)) return doubleValue; // 可根据需求添加更多数值类型支持,比如decimal throw new NotSupportedException($"无法解析的数字类型:{element.ValueKind}"); } /// <summary> /// 从JSON字符串直接转换为类Python结构 /// </summary> public static object ParseJsonString(string json) { using var doc = JsonDocument.Parse(json); return ConvertToPythonLikeStructure(doc.RootElement); } }
使用示例
拿你给出的JSON示例来测试:
{"array1": [{"property1": "value1", "property2": "value2"}]}
调用代码:
string json = @"{""array1"": [{""property1"": ""value1"", ""property2"": ""value2""}]}"; var result = JsonConverterUtils.ParseJsonString(json); // 像Python那样访问数据 var array1 = (List<object>)((Dictionary<string, object>)result)["array1"]; var firstObj = (Dictionary<string, object>)array1[0]; string value1 = (string)firstObj["property1"]; // 输出 "value1" string value2 = (string)firstObj["property2"]; // 输出 "value2"
可选:使用Newtonsoft.Json的实现
如果你项目里用的是Newtonsoft.Json(Json.NET),也可以用类似的递归逻辑:
using System.Collections.Generic; using Newtonsoft.Json.Linq; public static class NewtonsoftJsonConverterUtils { public static object ConvertToPythonLikeStructure(JToken token) { return token.Type switch { JTokenType.Object => ConvertJObject((JObject)token), JTokenType.Array => ConvertJArray((JArray)token), JTokenType.String => token.Value<string>(), JTokenType.Integer => token.Value<long>(), JTokenType.Float => token.Value<double>(), JTokenType.Boolean => token.Value<bool>(), JTokenType.Null => null, _ => throw new NotSupportedException($"不支持的JSON类型:{token.Type}") }; } private static Dictionary<string, object> ConvertJObject(JObject obj) { var dict = new Dictionary<string, object>(); foreach (var property in obj.Properties()) { dict.Add(property.Name, ConvertToPythonLikeStructure(property.Value)); } return dict; } private static List<object> ConvertJArray(JArray array) { var list = new List<object>(); foreach (var item in array) { list.Add(ConvertToPythonLikeStructure(item)); } return list; } public static object ParseJsonString(string json) { var token = JToken.Parse(json); return ConvertToPythonLikeStructure(token); } }
注意事项
- 因为是动态类型,访问时需要显式转换(比如
(List<object>)、(Dictionary<string, object>)),如果怕麻烦可以考虑用dynamic类型,但要注意运行时类型错误。 - 数值类型的处理可以根据你的需求调整,比如如果需要decimal,可以在
GetNumberValue里添加element.TryGetDecimal(out decimal decValue)的判断。 - 对于复杂的JSON结构(比如嵌套多层对象/数组),递归逻辑会自动处理,不用额外修改代码。
内容的提问来源于stack exchange,提问作者Duong Nhat
相关产品推荐
相关产品推荐

