You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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" }
          }
        ]
      }
    }
  }
}

问题分析

  1. 大小写不匹配:JSON键全是小写(比如reports、id),但C#默认用PascalCase命名,需要显式映射;
  2. step的混合类型:JSON中step既可能是单个对象(比如{"id":"7"}),也可能是数组(比如[{"id":"4"},{"id":"5"}]),C#无法直接用单一类型匹配;
  3. 类的访问修饰符与属性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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:08:38