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

C#解析JSON时同一属性兼具对象与列表类型的解决方法

这问题我太熟了!JSON里字段时而对象时而数组的情况真的很坑,尤其是反序列化的时候直接炸类型错误。别担心,咱们用自定义JSON转换器就能完美解决,顺便给你讲讲需要学习的核心知识点。

解决方法:自定义JSON转换器处理“单对象/数组”兼容问题

你用的是Newtonsoft.Json(Json.NET)对吧?它支持自定义JsonConverter来处理这种类型不稳定的字段。咱们先写一个通用的转换器,能把单个对象自动包装成列表,也能直接解析数组,这样所有类似的字段都能复用这个转换器。

步骤1:实现通用的SingleOrArrayConverter

这个转换器会自动判断JSON节点是对象还是数组,然后统一转成List<T>:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;

public class SingleOrArrayConverter<T> : JsonConverter
{
    // 告诉Json.NET这个转换器能处理List<T>类型
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(List<T>);
    }

    // 反序列化逻辑:读JSON时处理单对象/数组
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var token = JToken.Load(reader);
        // 如果是数组,直接转成List<T>
        if (token.Type == JTokenType.Array)
        {
            return token.ToObject<List<T>>();
        }
        // 如果是单个对象,包装成只有一个元素的列表
        return new List<T> { token.ToObject<T>() };
    }

    // 序列化逻辑(可选):如果列表只有一个元素,转成单个对象输出
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var list = value as List<T>;
        if (list != null && list.Count == 1)
        {
            serializer.Serialize(writer, list[0]);
        }
        else
        {
            serializer.Serialize(writer, list);
        }
    }
}

步骤2:修改实体类,给不稳定字段添加转换器

接下来修改你的实体类,把原本可能是单对象的属性改成List<T>(或者IList<T>),然后加上[JsonConverter]特性:

修改Events类的Event字段

原本的IList<Event>保留,加上转换器:

public class Events {
    [JsonProperty("num")]
    public int Num { get; set; }
    [JsonProperty("event")]
    [JsonConverter(typeof(SingleOrArrayConverter<Event>))]
    public IList<Event> Event { get; set; }
}

修改Subtypes类的Subtype字段

注意:原来的Subtype是单个对象类型,现在要改成IList<Subtype>,因为JSON里可能是数组:

public class Subtypes {
    [JsonProperty("num")]
    public int Num { get; set; }
    [JsonProperty("subtype")]
    [JsonConverter(typeof(SingleOrArrayConverter<Subtype>))]
    public IList<Subtype> Subtype { get; set; }
}

这样不管JSON里的event或subtype是单个对象还是数组,都能正常反序列化了!如果业务逻辑里需要取单个对象,只需要判断Subtype.Count == 1然后取Subtype[0]就行。


你需要学习的核心内容
  1. Json.NET自定义转换器:这是处理JSON兼容性问题的核心技能,掌握它之后大部分类型不匹配的问题都能解决。
  2. JSON结构分析能力:学会用JSON格式化工具快速识别哪些字段存在类型变化,提前做好兼容处理。
  3. C#泛型:上面的转换器用了泛型,让你不用给每个类型都写单独的转换器,大大提高代码复用性,泛型是C#里非常重要的特性。
  4. 可选:System.Text.Json转换器:如果你用的是.NET Core/.NET 5+自带的System.Text.Json,它也支持自定义转换器,思路和Json.NET一致,但API略有不同,也需要了解。

内容的提问来源于stack exchange,提问作者Vladson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:48:00