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

C#使用Newtonsoft.Json反序列化重名JSON字段的解决方法

问题根源

  1. 你获取的第三方JSON不符合常规规范:for对象下存在两个同名的total、average键,分别对应对象和基础值两种不同类型,Newtonsoft.Json默认的反序列化逻辑无法适配这种重复键+类型不一致的场景,会抛出类型匹配异常。
  2. 你定义的For类本身存在语法错误:C#不允许同一个类中定义多个同名(即使返回值类型不同)的属性,因此添加JsonProperty特性时会提示成员已存在。

解决方案

第一步:修正For类定义

首先删除重复的同名属性,为两类不同类型的total、average设置不同的属性名:

public class For
{
    // 存储基础值类型的total、average
    public int TotalValue { get; set; }
    public string AverageValue { get; set; }
    
    // 存储对象类型的total、average
    public Total TotalObj { get; set; }
    public Average AverageObj { get; set; }
    
    public Minute minute { get; set; }
    public int home { get; set; }
    public int away { get; set; }
}

public class Total {
    public int home { get; set; }
    public int away { get; set; }
    public int total { get; set; }
}

public class Average {
    public string home { get; set; }
    public string away { get; set; }
    public string total { get; set; }
}

第二步:选择适配的解析方式

方案1:JObject手动解析(适合单次解析场景)

直接将JSON解析为JObject,遍历属性手动处理重复键的赋值逻辑:

// jsonStr为第三方返回的完整JSON字符串
var rootJObj = JObject.Parse(jsonStr);
var forNode = rootJObj["for"] as JObject;
var forResult = new For();

foreach (var prop in forNode.Properties())
{
    switch (prop.Name)
    {
        case "total":
            if (prop.Value.Type == JTokenType.Object)
                forResult.TotalObj = prop.Value.ToObject<Total>();
            else if (prop.Value.Type == JTokenType.Integer)
                forResult.TotalValue = prop.Value.Value<int>();
            break;
        case "average":
            if (prop.Value.Type == JTokenType.Object)
                forResult.AverageObj = prop.Value.ToObject<Average>();
            else if (prop.Value.Type == JTokenType.String)
                forResult.AverageValue = prop.Value.Value<string>();
            break;
        case "minute":
            forResult.minute = prop.Value.ToObject<Minute>();
            break;
        case "home":
            forResult.home = prop.Value.Value<int>();
            break;
        case "away":
            forResult.away = prop.Value.Value<int>();
            break;
    }
}

方案2:自定义JsonConverter(适合批量解析场景)

如果需要多次解析该结构,可自定义转换器实现自动反序列化:

public class ForConverter : JsonConverter<For>
{
    public override For ReadJson(JsonReader reader, Type objectType, For existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var jObj = JObject.Load(reader);
        var forResult = new For();
        
        foreach (var prop in jObj.Properties())
        {
            if (prop.Name == "total")
            {
                if (prop.Value.Type == JTokenType.Object)
                    forResult.TotalObj = prop.Value.ToObject<Total>(serializer);
                else if (prop.Value.Type == JTokenType.Integer)
                    forResult.TotalValue = prop.Value.Value<int>();
            }
            else if (prop.Name == "average")
            {
                if (prop.Value.Type == JTokenType.Object)
                    forResult.AverageObj = prop.Value.ToObject<Average>(serializer);
                else if (prop.Value.Type == JTokenType.String)
                    forResult.AverageValue = prop.Value.Value<string>();
            }
            else
            {
                serializer.Populate(prop.Value.CreateReader(), forResult);
            }
        }
        return forResult;
    }

    public override void WriteJson(JsonWriter writer, For value, JsonSerializer serializer)
    {
        // 不需要序列化为原JSON格式可直接抛出异常
        throw new NotImplementedException();
    }
}

使用时传入转换器即可:

var forResult = JsonConvert.DeserializeObject<For>(jsonStr, new ForConverter());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 06:15:03