Newtonsoft JSON反序列化:空列表以{}代替[]引发异常的解决方案
解决Newtonsoft.Json兼容空列表为
{}的反序列化问题 问题背景
对接第三方API时遇到JSON格式不一致:列表有值时返回数组[],空列表时却返回空对象{},导致反序列化IList<T>类型时抛出JsonSerializationException。
现成配置说明
Newtonsoft.Json没有直接的内置配置开关来兼容这种情况,最优雅的解决方式是自定义JSON转换器,在反序列化阶段自动处理{}为空列表的场景。
实现方案:自定义JsonConverter
1. 编写泛型转换器
创建一个通用转换器,处理IList<T>类型的反序列化,遇到空对象时返回空列表:
public class EmptyObjectToListConverter<T> : JsonConverter<IList<T>> { public override IList<T> ReadJson(JsonReader reader, Type objectType, IList<T> existingValue, bool hasExistingValue, JsonSerializer serializer) { return reader.TokenType switch { JsonToken.StartArray => serializer.Deserialize<List<T>>(reader), JsonToken.StartObject => new List<T>(), JsonToken.Null => null, _ => throw new JsonSerializationException($"无法处理的Token类型:{reader.TokenType}") }; } public override void WriteJson(JsonWriter writer, IList<T> value, JsonSerializer serializer) { // 序列化时保持正常数组格式 serializer.Serialize(writer, value); } }
2. 应用转换器到目标属性
修改你的GenericNamedResponseObject类,在Info属性上添加转换器标记:
[Serializable] public class GenericNamedResponseObject { [JsonProperty("code")] public int? Code { get; set; } [JsonProperty("msg")] public string ErrorMessage { get; set; } private IList<GenericResponseLineItem> _info; [JsonProperty("info")] [JsonConverter(typeof(EmptyObjectToListConverter<GenericResponseLineItem>))] public IList<GenericResponseLineItem> Info { get => _info ?? (_info = new List<GenericResponseLineItem>()); set => _info = value; } }
3. (可选)全局注册转换器
如果多个地方都需要处理这种兼容场景,可以将转换器全局注册到JsonSerializerSettings,避免重复标记属性:
var jsonSettings = new JsonSerializerSettings(); jsonSettings.Converters.Add(new EmptyObjectToListConverter<GenericResponseLineItem>()); // 使用全局配置反序列化 var response = JsonConvert.DeserializeObject<GenericNamedResponseObject>(jsonString, jsonSettings);
方案优势
- 无需冗余的
try/catch重试逻辑,代码更简洁 - 精准控制特定类型的反序列化规则,不影响其他属性
- 序列化时保持标准数组格式,不会破坏输出规范
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

