C# .NET:使用System.Text.Json将JSON数组反序列化为IList<Interface>
解决System.Text.Json反序列化接口集合(如IList)的问题
System.Text.Json默认不支持直接将JSON数组反序列化为IList<TInterface>这类接口集合类型,要替代Newtonsoft.Json中JsonArrayAttribute+CustomCreationConverter<T>的组合,核心是自定义泛型转换器,明确指定集合和元素的具体实现类。
具体实现步骤:
1. 定义接口与具体实现类
假设我们有如下接口和具体类:
public interface IFoo { string Name { get; set; } } public class ConcreteFoo : IFoo { public string Name { get; set; } }
2. 自定义接口集合转换器
编写一个泛型转换器,实现JsonConverter<IList<TInterface>>,在反序列化时将JSON数组转为具体集合类型,再转换为接口集合:
public class InterfaceListConverter<TInterface, TConcrete> : JsonConverter<IList<TInterface>> where TConcrete : class, TInterface { public override IList<TInterface> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 先反序列化为具体元素的集合 var concreteItems = JsonSerializer.Deserialize<List<TConcrete>>(ref reader, options); // 转换为接口集合返回,空值则返回空列表 return concreteItems?.Cast<TInterface>().ToList() ?? new List<TInterface>(); } public override void Write(Utf8JsonWriter writer, IList<TInterface> value, JsonSerializerOptions options) { // 序列化时将接口集合转为具体类型集合再处理 JsonSerializer.Serialize(writer, value.Cast<TConcrete>(), options); } }
3. 使用转换器的两种方式
方式一:反序列化时手动传入配置
var jsonArray = @"[{""Name"":""FirstFoo""},{""Name"":""SecondFoo""}]"; var options = new JsonSerializerOptions(); // 添加自定义转换器 options.Converters.Add(new InterfaceListConverter<IFoo, ConcreteFoo>()); // 直接反序列化为IList<IFoo> var interfaceList = JsonSerializer.Deserialize<IList<IFoo>>(jsonArray, options);
方式二:给模型属性添加特性标记
如果接口集合是某个模型的属性,可以直接用JsonConverterAttribute指定转换器:
public class MyBusinessModel { [JsonConverter(typeof(InterfaceListConverter<IFoo, ConcreteFoo>))] public IList<IFoo> FooItems { get; set; } } // 反序列化模型 var model = JsonSerializer.Deserialize<MyBusinessModel>(jsonArray);
额外说明
- 如果需要支持其他集合接口(如
ICollection<TInterface>、IEnumerable<TInterface>),可以修改转换器的泛型参数,实现对应的JsonConverter接口即可。 - 若具体实现类没有无参构造函数,需要在
JsonSerializerOptions中配置允许使用非公共构造函数,或者确保类有可访问的无参构造。
内容的提问来源于stack exchange,提问作者codekandis
相关产品推荐
相关产品推荐

