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

C#反序列化含混合类型字段的嵌套JSON报错解决方案

问题根因

反序列化报错的核心原因是接口返回的partitions字段类型不统一,不符合静态类型语言的反序列化默认规则:

  • 部分返回记录里partitions是空字符串:"partitions": ""
  • 部分记录里partitions是标准的Partition对象数组:"partitions": [{"ref": "txtRef", "object1": "test", "dateFormat": "YYmmdd"}]
  • 部分记录里partitions是空数组:"partitions": []

你定义的实体类中把partitions固定声明为List<Partition>类型,Json.NET解析到字符串值时无法直接将其转换为集合类型,就会抛出字符解析错误。Python属于动态类型语言,对同字段多类型的兼容度更高,所以相同JSON可以正常解析。

之前尝试的几种方案不生效的原因也很明确:

  • 用dynamic接收只是绕过了编译时类型检查,后续访问partitions做集合操作时,遇到字符串值依然会抛出运行时错误,没有解决根本问题
  • 移除partitions字段相当于直接跳过该字段解析,本质是规避问题不是解决问题
  • 在线JSON转C#工具默认基于同名字段类型完全一致的规则生成代码,遇到这种接口返回不规范的多类型字段,生成的类自然无法正常反序列化。
解决方案

方案1:自定义JsonConverter兼容多类型(推荐,侵入性最低)

通过自定义JSON转换器,在反序列化阶段自动兼容partitions字段的多种格式,不需要修改后续业务逻辑:

  1. 编写自定义转换器,遇到空字符串、null值时直接返回空集合,遇到数组时正常反序列化为List<Partition>:
public class PartitionListConverter : JsonConverter<List<Partition>>
{
    public override List<Partition> ReadJson(JsonReader reader, Type objectType, List<Partition> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        return reader.TokenType switch
        {
            JsonToken.String or JsonToken.Null => new List<Partition>(),
            JsonToken.StartArray => JArray.Load(reader).ToObject<List<Partition>>(serializer),
            _ => throw new JsonSerializationException($"不支持的partitions字段类型: {reader.TokenType}")
        };
    }

    public override void WriteJson(JsonWriter writer, List<Partition> value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }
}
  1. 给实体类的partitions字段添加转换器标记:
public class dataSourceOptions
{
    [JsonConverter(typeof(PartitionListConverter))]
    public List<Partition> partitions { get; set; }
}

修改完成后,原有JsonConvert.DeserializeObject<testData>(response)代码不需要做任何调整,即可正常解析所有格式的返回值。

方案2:弱类型接收后二次转换

如果不想编写自定义转换器,可以先把partitions声明为通用JToken类型,反序列化完成后自行判断类型做转换:

  1. 修改dataSourceOptions类定义:
public class dataSourceOptions
{
    public JToken partitions { get; set; }
}
  1. 反序列化后手动处理类型转换:
testData data = JsonConvert.DeserializeObject<testData>(response);
foreach (var collectItem in data.dataList)
{
    List<Partition> realPartitions = new List<Partition>();
    if (collectItem.dataOptions.partitions is JArray arr)
    {
        realPartitions = arr.ToObject<List<Partition>>();
    }
    // 后续业务逻辑直接使用realPartitions即可
}

内容的提问来源于stack exchange,提问作者Boonrak K.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 21:45:44