如何使用System.Text.Json反序列化含无参公共构造函数的类
问题:带公共无参构造函数的C#类反序列化时属性无法正确赋值
在.NET 7.0的C#应用中,使用System.Text.Json进行序列化/反序列化时出现异常:
- 类
Works(私有无参构造+公共有参构造)反序列化后,address能正确获取JSON中的值"abc" - 类
Doesnt(标记[JsonConstructor]的公共无参构造+公共有参构造)反序列化后,address始终是无参构造里的"default"(移除初始化则为null)
示例代码
正常工作的Works类
public class Works { public string address { get; private set; } Works() { address = "default"; } public Works(string address) { this.address = address; } }
反序列化异常的Doesnt类
public class Doesnt { public string address { get; private set; } [JsonConstructor] public Doesnt() { address = "default"; } public Doesnt(string address) { this.address = address; } }
序列化与反序列化逻辑
public byte[] SerializeToBytes<T>(T src) { return JsonSerializer.SerializeToUtf8Bytes(src, SerializerOptions); } public object Deserialize(byte[] data, Type type) { object res; var str = System.Text.Encoding.UTF8.GetString(data); res = JsonSerializer.Deserialize(str, type, SerializerOptions); return res; } var objs = new object[]{new Works("abc"),new Doesnt("abc")}; var bytes = SerializeToBytes(objs[0]); Deserialize(bytes, objs[0].GetType());// 返回"abc" bytes = SerializeToBytes(objs[1]); Deserialize(bytes, objs[1].GetType()); // 返回"default"
解决方案
方法1:将[JsonConstructor]标记移至有参构造函数
把[JsonConstructor]从无参构造转移到接收address参数的有参构造上,让反序列化时优先调用该构造,直接用JSON中的值初始化属性:
public class Doesnt { public string address { get; private set; } public Doesnt() { address = "default"; } [JsonConstructor] // 标记有参构造 public Doesnt(string address) { this.address = address; } }
说明:此方法会跳过无参构造的执行逻辑,直接通过JSON值初始化对象,适合不需要保留无参构造初始化逻辑的场景。
方法2:给私有setter添加[JsonInclude]特性
通过[JsonInclude]允许System.Text.Json访问私有setter,这样反序列化时会先执行无参构造初始化,再用JSON值覆盖属性:
public class Doesnt { [JsonInclude] // 允许序列化/反序列化访问私有setter public string address { get; private set; } [JsonConstructor] public Doesnt() { address = "default"; } public Doesnt(string address) { this.address = address; } }
说明:此方法会保留无参构造的初始化逻辑,再用JSON值覆盖属性,适合需要保留默认初始化逻辑的场景。
内容的提问来源于stack exchange,提问作者Maxim Kitsenko
相关产品推荐
相关产品推荐

