.NET 8中为何无法反序列化带List<T>属性的对象?
System.Text.Json反序列化含List属性对象失败的原因与修复方案
问题根源
你的代码中,Parent类的Children属性只有get访问器,没有set访问器:
public List<Child> Children { get; } = new List<Child>();
System.Text.Json默认规则是:反序列化时需要属性具备可写能力(即存在setter),才能将JSON中的数据赋值到属性上。
直接反序列化List<Child>能成功,是因为序列化器会直接创建List<T>实例并填充数据;但反序列化Parent对象时,虽然属性初始化了一个空列表,序列化器却无法向这个只读属性对应的列表中添加数据——它既不能创建新列表赋值(没有setter),也默认不会修改已存在的集合实例。
另外,Child类的带参构造函数不影响这个问题(.NET 5+的System.Text.Json默认支持构造函数绑定,所以直接反序列化List<Child>可行)。
修复方案
方案1:给属性添加私有setter
保留外部只读的语义,同时让序列化器能通过反射访问私有setter来赋值:
public class Parent { public List<Child> Children { get; private set; } = new List<Child>(); }
这种方式最简单,不需要修改序列化配置。
方案2:使用序列化配置允许修改只读集合
如果想完全保留属性的只读特性(不添加任何setter),可以配置JsonSerializerOptions让序列化器直接修改已初始化的集合实例:
// 配置序列化选项 var options = new JsonSerializerOptions { AllowReadOnlyProperties = true, PropertyNameCaseInsensitive = true // 可选,增强兼容性 }; // 反序列化时传入配置 var deserializedParent = JsonSerializer.Deserialize<Parent>(parentJson, options);
Parent类保持原有代码不变即可,序列化器会自动把JSON中的Children数组元素添加到已初始化的空列表中。
验证效果
修改后重新运行测试,反序列化后的Parent对象Children属性会正确包含Child A和Child B,断言parentJson == parentJson2将成功通过。
内容的提问来源于stack exchange,提问作者Kairei
相关产品推荐
相关产品推荐

