实现IReadOnlyCollection的类无法用System.Text.Json反序列化的问题
问题分析与解决方案
你的问题核心是:System.Text.Json默认会将实现IReadOnlyCollection<T>等集合接口的类视为「集合类型」,反序列化时优先走集合的添加逻辑而非对象构造逻辑。哪怕你标记了[JsonConstructor],序列化器也不会调用它——因为它觉得这是个集合,应该创建实例后往里面加元素,但你的MyItems是只读集合,没有Add方法,所以抛出NotSupportedException。
参数名称不是问题,因为JSON是数组结构(而非键值对),序列化器会直接把数组内容传给构造函数的可枚举类型参数,只要参数类型匹配(比如IEnumerable<int>、int[]、List<int>)即可。
可选解决方案(无需自定义Converter优先)
1. 用[JsonObject]标记类,强制序列化器当作对象处理
给MyItems类加上[JsonObject]特性,告诉System.Text.Json:这不是普通集合,是一个需要通过构造函数实例化的对象。
示例代码:
using System.Collections; using System.Collections.Generic; using System.Text.Json.Serialization; [JsonObject] public class MyItems : IReadOnlyCollection<int> { private readonly List<int> _items; [JsonConstructor] public MyItems(IEnumerable<int> items) { _items = new List<int>(items); } public int Count => _items.Count; public IEnumerator<int> GetEnumerator() => _items.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); }
这样反序列化时,序列化器会自动解析JSON数组,将其作为参数传入标记了[JsonConstructor]的构造函数,无需额外转换器。
自定义Converter方案(更灵活的场景)
如果你的MyItems有复杂的逻辑,或者不想依赖[JsonObject]特性,可以自定义JsonConverter来完全控制序列化/反序列化流程:
public class MyItemsConverter : JsonConverter<MyItems> { public override MyItems Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 先把JSON数组反序列化为List<int>,再传入构造函数 var items = JsonSerializer.Deserialize<List<int>>(ref reader, options); return new MyItems(items); } public override void Write(Utf8JsonWriter writer, MyItems value, JsonSerializerOptions options) { // 序列化时直接把MyItems当作IEnumerable<int>输出 JsonSerializer.Serialize(writer, value as IEnumerable<int>, options); } }
然后给MyItems类添加转换器标记:
[JsonConverter(typeof(MyItemsConverter))] public class MyItems : IReadOnlyCollection<int> { // ... 类实现代码 ... }
或者在序列化/反序列化时传入配置:
var options = new JsonSerializerOptions(); options.Converters.Add(new MyItemsConverter()); var myItems = JsonSerializer.Deserialize<MyItems>("[1,2,3]", options);
不推荐的方案
不要为了适配序列化而给只读集合添加Add方法(实现ICollection<int>),这会破坏只读集合的设计意图,导致类的行为不符合预期。
内容的提问来源于stack exchange,提问作者grim.ub
相关产品推荐
相关产品推荐

