如何用System.Text.Json自定义转换器兼容解析单对象和列表JSON
实现方案
步骤1:编写通用自定义JsonConverter
继承JsonConverter<IList<T>>实现自动适配单对象/数组的解析逻辑:
using System.Text.Json; using System.Text.Json.Serialization; public class SingleOrArrayConverter<T> : JsonConverter<IList<T>> { public override IList<T>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { switch (reader.TokenType) { // 传入为数组格式,正常解析 case JsonTokenType.StartArray: return JsonSerializer.Deserialize<List<T>>(ref reader, options); // 传入为单个对象,解析后包装为列表返回 case JsonTokenType.StartObject: var singleItem = JsonSerializer.Deserialize<T>(ref reader, options); return singleItem == null ? new List<T>() : new List<T> { singleItem }; // 空值处理,可按需调整为返回null case JsonTokenType.Null: return new List<T>(); default: throw new JsonException($"不支持的令牌类型:{reader.TokenType}"); } } public override void Write(Utf8JsonWriter writer, IList<T> value, JsonSerializerOptions options) { // 序列化默认输出数组格式,若需要适配单对象输出可自行修改此处逻辑 JsonSerializer.Serialize(writer, value, options); } }
步骤2:使用转换器
在反序列化时注册转换器即可同时兼容两种响应格式:
// 配置序列化参数 var jsonOptions = new JsonSerializerOptions(); jsonOptions.Converters.Add(new SingleOrArrayConverter<ExampleResponse>()); // 执行反序列化,无需判断响应格式 var response = JsonSerializer.Deserialize<IList<ExampleResponse>>(content, jsonOptions);
如果需要全局适配,也可以直接给对应实体类的集合属性添加特性:[JsonConverter(typeof(SingleOrArrayConverter<ExampleResponse>))]。
验证效果
- 当返回示例1的数组格式时,
response为对应长度的IList<ExampleResponse>集合 - 当返回示例2的单对象格式时,
response为长度为1的IList<ExampleResponse>集合,元素为返回的单个对象
内容的提问来源于stack exchange,提问作者Manuel
相关产品推荐
相关产品推荐

