Newtonsoft.Json
确保类具有公共或私有的无参构造函数。
如果想绑定到特定构造函数,可以使用 [JsonConstructor] 特性,例如:
csharp
复制代码
收起
public class Person
{
public string Name { get; }
public int Age { get; }
[JsonConstructor]
public Person(string name, int age)
{
Console.WriteLine("构造函数调用!");
Name = name;
Age = age;
}
}
复制
这样在反序列化时会调用该构造函数。
System.Text.Json
必须有一个适用的构造器(public 或 internal),且参数名与 JSON 属性匹配。
用 [JsonConstructor] 明确标记要用的构造函数。
csharp
复制代码
收起
public class Person
{
public string Name { get; }
public int Age { get; }
[JsonConstructor]
public Person(string name, int age)
{
Console.WriteLine("构造函数调用!");
Name = name;
Age = age;
}
}
复制
3. 总结
默认反序列化:很可能绕过你自定义的构造函数(特别是 Newtonsoft.Json)。
需要构造器逻辑:使用 [JsonConstructor] 或提供无参构造函数。
初始化逻辑替代:如果不能依赖构造函数,可用反序列化回调特性:
Newtonsoft.Json: IJsonSerializable、OnDeserialized 属性。
System.Text.Json: OnDeserialized 方法在较新版本里可支持(.NET 8+)。
原来是这样的原因,学到了!
坑2:C#中用json序列化方式读取并生成的类对象,不会触发调用构造函数
如果在构造函数中设置了id的自增,则会发现id没有变化
是的,你的观察是正确的。
在 C# 中,当你使用常见的 JSON 序列化/反序列化库(例如 Newtonsoft.Json、System.Text.Json)去 反序列化 JSON 字符串成为一个类对象时,默认情况下不会调用类的普通构造函数。
1. 为什么构造函数不会被调用?
JSON 反序列化过程本质上是通过反射直接创建对象实例并为其字段/属性赋值,而不是像 new MyClass() 那样调用构造函数。
以 Newtonsoft.Json 为例:
默认反序列化时会用 FormatterServices.GetUninitializedObject()(或类似机制)在内存中分配对象,不走用户定义的构造函数。
然后根据 JSON 字段,把属性或字段的值用反射赋进去。
System.Text.Json(.NET Core 3.1+)则:
默认使用无参数构造函数(如果存在且可访问)。
如果类没有无参构造函数,就用非常规实例化方式(类似反射直接创建),绕过你的自定义构造函数逻辑。
2. 如何让反序列化调用构造函数?
如果你的反序列化需要执行构造函数逻辑(比如初始化某些数据),需要做以下处理:
Newtonsoft.Json
确保类具有公共或私有的无参构造函数。
如果想绑定到特定构造函数,可以使用 [JsonConstructor] 特性,例如:
csharp
复制代码
收起
public class Person
{
public string Name { get; }
public int Age { get; }
[JsonConstructor]
public Person(string name, int age)
{
Console.WriteLine("构造函数调用!");
Name = name;
Age = age;
}
}
复制
这样在反序列化时会调用该构造函数。
System.Text.Json
必须有一个适用的构造器(public 或 internal),且参数名与 JSON 属性匹配。
用 [JsonConstructor] 明确标记要用的构造函数。
csharp
复制代码
收起
public class Person
{
public string Name { get; }
public int Age { get; }
[JsonConstructor]
public Person(string name, int age)
{
Console.WriteLine("构造函数调用!");
Name = name;
Age = age;
}
}
复制
3. 总结
默认反序列化:很可能绕过你自定义的构造函数(特别是 Newtonsoft.Json)。
需要构造器逻辑:使用 [JsonConstructor] 或提供无参构造函数。
初始化逻辑替代:如果不能依赖构造函数,可用反序列化回调特性:
Newtonsoft.Json: IJsonSerializable、OnDeserialized 属性。
System.Text.Json: OnDeserialized 方法在较新版本里可支持(.NET 8+)。
如果你愿意的话,我可以帮你写一个 Newtonsoft.Json 和 System.Text.Json 的反序列化对比示例,让你直观看到构造函数是否被调用以及如何强制调用。
你要我帮你做这个演示吗?