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

使用自定义Newtonsoft JSON转换器解析含重复属性键的无效JSON

你现有实现的可优化点:

  • 硬编码了quotes、quotes.quote路径,后续如果属性名调整或者需要复用Converter时会失效
  • 手动控制JsonReader遍历逻辑容易出现节点读取偏差,影响后续其他字段的解析

下面是两种更简便稳定的实现方案:

方案1:高版本Newtonsoft(12.0.1+)最优实现

利用Newtonsoft原生的重复属性处理配置,结合LINQ to JSON实现,代码更简洁易维护。
第一步:反序列化时添加配置,允许保留重复属性:

var deserializeSettings = new JsonSerializerSettings
{
    DuplicatePropertyNameHandling = DuplicatePropertyNameHandling.All
};
var result = JsonConvert.DeserializeObject<MyTestObject>(invalidJson, deserializeSettings);

第二步:简化Converter实现:

public class NewtonsoftQuoteListConverter : JsonConverter<IEnumerable<Quote>>
{
    public override IEnumerable<Quote> ReadJson(JsonReader reader, Type objectType, IEnumerable<Quote> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null) return null;
        var quoteContainer = JObject.Load(reader);
        return quoteContainer.Properties()
            .Where(p => p.Name.Equals("Quote", StringComparison.OrdinalIgnoreCase))
            .Select(p => p.Value.ToObject<Quote>(serializer))
            .ToList();
    }

    public override void WriteJson(JsonWriter writer, IEnumerable<Quote> value, JsonSerializer serializer)
        => throw new NotImplementedException("仅支持读取操作");
}

优势:

  • 无硬编码路径,和外层属性名解耦,可复用性更高
  • 不用手动处理JsonReader的遍历逻辑,避免节点读取错误
  • 代码量少,可读性高

方案2:低版本Newtonsoft兼容实现

如果你的Newtonsoft版本低于12.0.1,不支持DuplicatePropertyNameHandling配置,可以优化你原来的Reader遍历逻辑,去掉硬编码路径:

public override IEnumerable<Quote> ReadJson(JsonReader reader, Type objectType, IEnumerable<Quote> existingValue, bool hasExistingValue, JsonSerializer serializer)
{
    if (reader.TokenType == JsonToken.Null) return null;
    var quotes = new List<Quote>();
    // 跳过Quotes对象的StartObject标记
    reader.Read();
    // 遍历直到Quotes对象结束
    while (reader.TokenType != JsonToken.EndObject)
    {
        if (reader.TokenType == JsonToken.PropertyName 
            && reader.Value.ToString().Equals("Quote", StringComparison.OrdinalIgnoreCase))
        {
            reader.Read(); // 跳到Quote对象的起始位置
            quotes.Add(serializer.Deserialize<Quote>(reader));
        }
        reader.Read();
    }
    return quotes;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 04:45:04