.NET 5 序列化变更:非公共无参构造函数不再用于反序列化

.NET 5 序列化变更:非公共无参构造函数不再用于反序列化

docs This repository contains .NET Documentation. docs 项目地址: 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 在反序列化时将遵循以下优先级选择构造函数:

  1. 首先查找带有 [JsonConstructor] 特性的公共构造函数
  2. 如果没有,则查找公共无参构造函数
  3. 如果也没有,则查找唯一的公共参数化构造函数

如果以上构造函数都不存在,尝试反序列化该类型时将抛出 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());

设计考量

这一变更主要基于以下设计原则:

  1. 一致性:统一不同目标框架下的行为
  2. 安全性:序列化器不应绕过类型的访问控制机制
  3. 明确性:通过特性明确指定反序列化行为,避免隐式逻辑

总结

.NET 5 中 System.Text.Json 的这一变更虽然可能影响现有代码,但它带来了更一致和安全的序列化行为。开发者应当:

  1. 检查项目中是否有依赖非公共构造函数的反序列化逻辑
  2. 根据需要采用上述解决方案进行调整
  3. 在设计中优先考虑使用公共构造函数或明确的 [JsonConstructor] 特性

这一改进使得 System.Text.Json 在跨平台场景下的行为更加可预测,同时也为未来的功能扩展奠定了更好的基础。

docs This repository contains .NET Documentation. docs 项目地址: https://gitcode.com/gh_mirrors/docs2/docs

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

翟万实Robust

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值