C#递归JSON解析失败求助:无法将JSON字符串映射至自定义类
解决JSON解析到C#类的问题
我看你遇到的核心问题是这段JSON里的step字段是混合类型(有时候是单个对象,有时候是数组),再加上类定义的一些细节没处理好,导致解析失败。咱们一步步来解决:
首先,先修正合法的JSON格式
你给的JSON键没有加双引号,这是不合法的,先改成标准格式:
{ "reports": { "report": { "id": "1", "step": { "id": "2", "step": [ { "id": "3", "step": [ { "id": "4" }, { "id": "5" } ] }, { "id": "6", "step": { "id": "7" } } ] } } } }
问题分析
- 大小写不匹配:JSON键全是小写(比如
reports、id),但C#默认用PascalCase命名,需要显式映射; step的混合类型:JSON中step既可能是单个对象(比如{"id":"7"}),也可能是数组(比如[{"id":"4"},{"id":"5"}]),C#无法直接用单一类型匹配;- 类的访问修饰符与属性get/set:你定义的类是
private,序列化器无法访问;属性没有get/set,无法赋值。
解决方案
1. 自定义JSON转换器处理混合类型
我们需要一个转换器,把单个对象自动转为包含一个元素的列表,反之亦然:
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.Collections.Generic; public class SingleOrArrayConverter<T> : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(List<T>); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var token = JToken.Load(reader); // 如果是数组,直接转成List<T>;如果是单个对象,包装成List return token.Type == JTokenType.Array ? token.ToObject<List<T>>() : new List<T> { token.ToObject<T>() }; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var list = (List<T>)value; // 序列化时,如果列表只有一个元素,直接序列化单个对象,否则序列化数组 if (list.Count == 1) { serializer.Serialize(writer, list[0]); } else { serializer.Serialize(writer, list); } } }
2. 正确定义匹配的C#类
注意用[JsonProperty]映射JSON键,属性要有get/set,类设为public:
public class RootObject { [JsonProperty("reports")] public Reports Reports { get; set; } } public class Reports { [JsonProperty("report")] public Report Report { get; set; } } public class Report { [JsonProperty("id")] public string Id { get; set; } [JsonProperty("step")] public Step Step { get; set; } } public class Step { [JsonProperty("id")] public string Id { get; set; } // 用自定义转换器处理混合类型的step字段,命名为SubSteps避免和类名冲突 [JsonProperty("step")] [JsonConverter(typeof(SingleOrArrayConverter<Step>))] public List<Step> SubSteps { get; set; } }
3. 解析JSON的示例代码
用Newtonsoft.Json(也就是Json.NET)来解析:
string json = @"{""reports"": {""report"": {""id"":""1"",""step"": {""id"":""2"",""step"": [ {""id"":""3"",""step"": [ {""id"":""4""}, {""id"":""5""} ] }, {""id"":""6"",""step"": {""id"":""7""} } ] } } }"; var root = JsonConvert.DeserializeObject<RootObject>(json); // 测试访问嵌套的属性 Console.WriteLine($"最外层report的ID: {root.Reports.Report.Id}"); Console.WriteLine($"第一层step的ID: {root.Reports.Report.Step.Id}"); Console.WriteLine($"第二层第一个step的ID: {root.Reports.Report.Step.SubSteps[0].Id}"); Console.WriteLine($"第三层第二个step的ID: {root.Reports.Report.Step.SubSteps[0].SubSteps[1].Id}"); Console.WriteLine($"第二层第二个step下的子step ID: {root.Reports.Report.Step.SubSteps[1].SubSteps[0].Id}");
注意事项
- 如果你用的是.NET Core/.NET 5+的System.Text.Json,也可以写类似的自定义转换器,原理一样;
- 确保已经安装了Newtonsoft.Json包(NuGet命令:
Install-Package Newtonsoft.Json)。
内容的提问来源于stack exchange,提问作者wallage
相关产品推荐
相关产品推荐

