使用自定义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
相关产品推荐
相关产品推荐

