Newtonsoft.Json反序列化处理result对象/空数组类型兼容问题
解决Newtonsoft.Json反序列化字段类型不兼容问题
针对REST接口同字段返回空数组/对象两种结构、无法修改接口实现的场景,可通过以下两种客户端方案兼容,不需要改动原有业务实体的核心逻辑。
方案1:自定义JsonConverter(推荐)
该方案对业务逻辑无侵入,反序列化时自动兼容两种格式,是最规范的实现方式。
- 编写通用的空数组转对象转换器,遇到空数组时自动初始化对应类型的实例,遇到正常对象时走默认反序列化逻辑:
public class EmptyArrayToObjectConverter<T> : JsonConverter where T : new() { public override bool CanConvert(Type objectType) => objectType == typeof(T); public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JToken token = JToken.Load(reader); return token.Type switch { JTokenType.Array => token.HasValues ? token.ToObject<T>(serializer) : new T(), JTokenType.Object => token.ToObject<T>(serializer), _ => null }; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { serializer.Serialize(writer, value); } }
- 给实体类的
Result属性添加转换器标记:
public class DuplicateResponseBody { [JsonProperty("result")] [JsonConverter(typeof(EmptyArrayToObjectConverter<ContactCompany>))] public ContactCompany Result { get; set; } }
- (可选)如果需要无数据场景下数组字段默认返回空数组而非null,可给
ContactCompany添加无参构造函数初始化:
public class ContactCompany { public ContactCompany() { ContactIds = Array.Empty<int>(); CompanyIds = Array.Empty<int>(); } [JsonProperty("CONTACT")] public int[] ContactIds { get; set; } [JsonProperty("COMPANY")] public int[] CompanyIds { get; set; } }
该转换器是通用实现,后续其他字段遇到同类「空数组代替空对象」的返回格式,都可以直接复用,不需要重复编写逻辑。
方案2:JToken中转解析(轻量场景适用)
如果项目中只有这一处存在类型不匹配问题,不想额外编写转换器类,可以直接将字段定义为JToken类型,反序列化后自行做类型判断:
public class DuplicateResponseBody { [JsonProperty("result")] private JToken _resultToken; // 忽略序列化特性,业务代码直接访问该属性拿解析结果 [JsonIgnore] public ContactCompany Result => _resultToken.Type switch { JTokenType.Array => new ContactCompany(), JTokenType.Object => _resultToken.ToObject<ContactCompany>(), _ => null }; }
该方案代码量更少,但仅适合少量字段的兼容场景,如果多处存在同类问题,优先使用方案1的通用转换器。
内容的提问来源于stack exchange,提问作者BennoDual
相关产品推荐
相关产品推荐

