假设下面的类定义

public class Foo
{
    [JsonProperty]
    public int Number { get; set; }

    [JsonProperty]
    public string Text { get; set; }
}

我现在需要属性Textconditionally required.例如,当Number > 10时,我需要Text出现在JSON字符串中.如果是Number <= 10,则可以省略.I cannot简单地使用属性的Required属性

[JsonProperty(Required = Required.Always)]
public string Text { get;set; }

因为这是无条件的.有什么办法可以让我强制执行吗?一些示例

{ "Number": 5 } // < valid 
{ "Number": 20 } // < invalid
{ "Number": 20, "Text": "Bar" } // < valid

我们的项目正在. NET Framework v4.8中使用Newtonsoft Json 我们的类是使用中间件序列化的(即我们在IIS上运行API).我们不会在任何地方手动呼叫JsonConvert.Deserizalize<T>(input).

推荐答案

如果希望在Number为10时强制Text存在且不为空,并且需要纯Newtonsoft解决方案,则可以在参数化构造函数中执行此操作:

public class Foo
{
    [JsonConstructor]
    // Make public if you want to enforce the same requirements during regular construction
    protected Foo(int number, string text) 
    {
        if (number > 10 && text == null)
            throw new ArgumentException("missing text");
        this.Number = number;
        this.Text = text;
    }
    
    // Remove if you want to enforce the same requirements during regular construction
    public Foo() { }
    
    [JsonProperty(Required = Required.Always)]
    public int Number { get; set; }

    public string Text { get; set; }
}

请注意,构造函数参数的名称必须与相应的属性相同,忽略大小写的差异.

here.第一次见面

或者,如果出于某种原因不喜欢使用构造函数,可以在[OnDeserialized]回调中进行判断:

public class Foo
{
    [JsonProperty(Required = Required.Always)]
    public int Number { get; set; }

    public string Text { get; set; }
    
    [System.Runtime.Serialization.OnDeserialized]
    void OnDeserializedMethod(System.Runtime.Serialization.StreamingContext context)
    {
        if (Number > 10 && Text == null)
        {
            throw new JsonSerializationException("missing text");
        }
    }
}

here.第一次见面

请注意,两种解决方案都将null的值与Text等同于缺失值. 如果你想让{"Number":20, "Text":null}有效,你需要采用一个更复杂的解决方案,比如记住Text是否曾经被设置过,并在[OnDeserialized]回调中判断它:

public class Foo
{
    [JsonProperty(Required = Required.Always)]
    public int Number { get; set; }

    string text;
    bool textSpecified;
    public string Text { get => text; set { text = value; textSpecified = true; } }
    
    [System.Runtime.Serialization.OnDeserialized]
    void OnDeserializedMethod(System.Runtime.Serialization.StreamingContext context)
    {
        if (Number > 10 && !textSpecified)
        {
            throw new JsonSerializationException("missing text");
        }
    }
}

演示小提琴#3 here.

Csharp相关问答推荐

当MD5被废弃时,如何在Blazor WASM中使用它?

有没有方法让ASP.NET Core模型绑定器使用私有设置器来设置属性?

如何模拟耐久任务客户端在统一测试和获取错误在调度NewsListationInstanceAsync模拟设置

.NET 6控制台应用程序,RabbitMQ消费不工作时,它的程序文件中的S

System.Net.Http.HttpClient.SendAsync(request)在docker容器内的POST方法30秒后停止

在允许溢出的情况下将小数转换为长

Polly重试URL复制值

如何允许数组接受多个类型?

WPF DataGrid文件名列,允许直接输入文本或通过对话框按键浏览

C#中类库项目的源代码生成器

ASP.NET MVC数据批注验证组复选框

如何使用IHostedService添加数据种子方法

Xamarin.Forms项目中缺少MainPage.xaml

最小API定义的Swagger标头参数

我想我必须手动使用res1(字符串形式的PowerShell哈希表)

我什么时候不应该在Dispose中调用EgSuppressFinalize(This)?

分别切换用于读取和写入的EF核心日志(log)

如何使用moq和xUnit对删除操作进行单元测试?

同时通过多个IEumable<;T&>枚举

C#Web服务转换为 node /Express不工作