.NET 5 序列化变更:非公共无参构造函数不再用于反序列化
docs This repository contains .NET Documentation. 项目地址: https://gitcode.com/gh_mirrors/docs2/docs
前言
在 .NET 5 中,System.Text.Json 序列化库引入了一项重要的行为变更:默认情况下,非公共(non-public)的无参构造函数将不再用于 JSON 反序列化操作。这一变更旨在统一不同目标框架下的序列化行为,并加强类型安全性的设计原则。
变更背景
在 .NET Core 3.x 版本中,System.Text.Json 序列化器允许使用内部(internal)和私有(private)的无参构造函数进行反序列化。然而,当开发者通过 NuGet 包在 .NET Standard 2.0 项目中使用 System.Text.Json 时(版本 4.6.0-4.7.2),行为却有所不同——这些版本会忽略非公共构造函数,如果没有可用的公共无参构造函数,就会抛出 MissingMethodException。
这种不一致性给跨平台开发带来了困扰。.NET 5 通过统一行为解决了这个问题,同时也遵循了"不应通过序列化器调用类型的非公共成员"的安全设计原则。
变更详情
从 .NET 5 开始,JsonSerializer 在反序列化时将遵循以下优先级选择构造函数:
- 首先查找带有 [JsonConstructor] 特性的公共构造函数
- 如果没有,则查找公共无参构造函数
- 如果也没有,则查找唯一的公共参数化构造函数
如果以上构造函数都不存在,尝试反序列化该类型时将抛出 NotSupportedException。特别注意:非公共构造函数(包括无参构造函数)将完全被忽略。
实际影响示例
假设有以下类定义:
public class Product
{
private Product() {} // .NET Core 3.x 可用,.NET 5 将被忽略
[JsonConstructor]
public Product(string name) {} // .NET 5 优先使用
public Product() {} // 次优选择
}
在 .NET 5 中:
- 将优先使用带 [JsonConstructor] 的构造函数
- 如果没有该特性,则使用公共无参构造函数
- 私有构造函数将被忽略
解决方案建议
方案一:修改类型定义(推荐)
如果类型在你的控制范围内,最简单的解决方案是将需要的无参构造函数改为公共的:
public class MyClass
{
public MyClass() {} // 改为公共构造函数
}
方案二:使用 JsonConverter
对于不能修改的第三方类型,可以实现自定义 JsonConverter:
public class PrivateConstructorConverter : JsonConverter<MyClass>
{
public override MyClass Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
// 在这里实现自定义反序列化逻辑
return Activator.CreateInstance(typeof(MyClass), nonPublic: true) as MyClass;
}
public override void Write(...) { ... }
}
然后在序列化时注册这个转换器:
options.Converters.Add(new PrivateConstructorConverter());
设计考量
这一变更主要基于以下设计原则:
- 一致性:统一不同目标框架下的行为
- 安全性:序列化器不应绕过类型的访问控制机制
- 明确性:通过特性明确指定反序列化行为,避免隐式逻辑
总结
.NET 5 中 System.Text.Json 的这一变更虽然可能影响现有代码,但它带来了更一致和安全的序列化行为。开发者应当:
- 检查项目中是否有依赖非公共构造函数的反序列化逻辑
- 根据需要采用上述解决方案进行调整
- 在设计中优先考虑使用公共构造函数或明确的 [JsonConstructor] 特性
这一改进使得 System.Text.Json 在跨平台场景下的行为更加可预测,同时也为未来的功能扩展奠定了更好的基础。
docs This repository contains .NET Documentation. 项目地址: https://gitcode.com/gh_mirrors/docs2/docs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考