You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6 JsonSerializer.DeserializeAsync null赋值非空属性异常解决方法

问题原因

System.Text.Json 默认存在以下行为,是该问题的核心诱因:

  • 不会自动识别[Required]这类数据注解特性,默认不会执行非空校验逻辑
  • C# 定义的非空引用类型约束属于编译期检查,运行时序列化器不会主动拦截null赋值操作
  • 反序列化时如果JSON缺失构造函数对应的参数,会默认传入null作为参数值,若构造函数内无null校验逻辑,就会直接把null赋值给声明为非空的属性
修复方案

根据项目使用的.NET版本,选择对应方案即可:

.NET 7及以上版本(最优方案)

直接配置JsonSerializerOptions的两个参数即可实现预期效果,无需修改实体类代码:

var jsonOptions = new JsonSerializerOptions
{
    // 识别C#非空引用类型注解,非空属性/参数收到null值时直接抛出JsonException
    RespectNullableAnnotations = true,
    // 强制构造函数定义的必填参数不可缺失,JSON缺省对应字段时直接抛出异常
    RespectRequiredConstructorParameters = true
};

// 反序列化时传入上述配置即可
var result = await JsonSerializer.DeserializeAsync<ArchiveData>(requestStream, jsonOptions);

配置生效后,只要JSON缺失必填字段、或给非空字段传递null值,都会直接抛出异常,不会再出现非空属性被赋值为null的情况。

.NET 6及以下版本

低版本System.Text.Json没有上述两个内置配置,通过两步实现需求:

  1. 给实体类构造函数添加null校验,拦截传入的null值:
[JsonConstructor]
public ArchiveData(long[] time, SensorArchiveValues[] sensorsArchiveValues)
{
    Time = time ?? throw new ArgumentNullException(nameof(time), "time字段不可为null");
    SensorsArchiveValues = sensorsArchiveValues ?? throw new ArgumentNullException(nameof(sensorsArchiveValues), "sensorsArchiveValues为必填字段");
}
  1. 反序列化完成后手动触发数据注解校验,让[Required]特性生效:
var archiveData = await JsonSerializer.DeserializeAsync<ArchiveData>(requestStream);
// 执行全属性校验,[Required]标记的属性为null时会抛出ValidationException
var validationContext = new ValidationContext(archiveData);
Validator.ValidateObject(archiveData, validationContext, validateAllProperties: true);

如果你是在ASP.NET Core接口中通过模型绑定直接接收参数(而非手动读取请求流调用反序列化),框架会自动执行上述校验逻辑,无需手动编写校验代码。

补充说明

代码中添加的[Required]特性属于System.ComponentModel.DataAnnotations下的数据注解,仅在ASP.NET Core模型绑定流程、或手动调用Validator类时生效,JsonSerializer本身不会主动解析执行该特性的校验逻辑,这也是加了特性依然不生效的核心原因。

内容的提问来源于stack exchange,提问作者hheimerd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 13:09:16