System.Text.Json中[JsonIgnore]被[Required]覆盖?PUT验证失败如何修复?
核心原因
不是[JsonIgnore]和[Required]的优先级问题,而是ASP.NET Core的模型验证会遍历整个对象图,包括你在Child类里默认初始化的空Parent实例。
你在Child类里给Parent属性默认赋值了new Parent(),这个空对象的Prop1/Prop2/Prop3虽然有默认的string.Empty,但[Required(AllowEmptyStrings = false)]会判定空字符串不合法。而[JsonIgnore]只控制序列化/反序列化是否处理这个属性,管不了模型验证对已存在的对象实例的校验。
解决方案
根据你的需求,这里有几种可行的修复方式:
1. 将Child的Parent属性设为可空(推荐)
把Child类里的Parent属性改为可空类型,并且去掉默认初始化:
public class Child { public int Id { get; set; } [JsonIgnore] public Parent? Parent { get; set; } // 改为可空,不默认初始化 [Required] public int ChildProp { get; set; } }
这样反序列化后Parent属性是null,模型验证不会去校验null对象的字段,自然不会触发必填错误。
2. 给Child的Parent属性添加[ValidateNever]特性
如果必须保留Parent属性的非空初始化,直接告诉模型验证器跳过这个属性的校验:
public class Child { public int Id { get; set; } [JsonIgnore] [ValidateNever] // 新增特性,跳过该属性及子属性的验证 public Parent Parent { get; set; } = new(); [Required] public int ChildProp { get; set; } }
[ValidateNever]是ASP.NET Core自带的特性,作用就是让模型验证忽略标记的属性及其子属性。
3. 全局配置跳过带[JsonIgnore]的属性验证
如果项目里有很多类似场景,可以全局配置模型验证规则,自动跳过所有带[JsonIgnore]的属性:
在Program.cs里添加以下代码:
builder.Services.AddControllers(options => { options.ModelValidatorProviders.RemoveType<DefaultModelValidatorProvider>(); options.ModelValidatorProviders.Add(new IgnoreJsonIgnoredPropertiesValidatorProvider()); }); // 自定义验证器提供类 public class IgnoreJsonIgnoredPropertiesValidatorProvider : IModelValidatorProvider { public void CreateValidators(ModelValidatorProviderContext context) { if (context.ModelMetadata.PropertyInfo?.GetCustomAttribute<JsonIgnoreAttribute>() != null) { // 若属性带有JsonIgnore,清空验证器以跳过校验 context.Validators.Clear(); } } }
这个方式一劳永逸,所有被[JsonIgnore]标记的属性都会被模型验证忽略。
补充说明
你之前尝试的JsonIgnore的Condition参数没用,是因为这个参数只影响序列化/反序列化时是否忽略属性,和模型验证完全是两个独立的流程,模型验证不关心这个参数的设置。
内容的提问来源于stack exchange,提问作者HWS-SLS

