JSON.Net中的业务验证

时间:2019-03-13 13:18:20

标签: c# .net json json.net

考虑到我们有一种描述参加AB测试结果的类型

public class ABTest
{
    [JsonProperty(Required = Required.Always)]
    public ulong CountOfAs { get; set; }
    [JsonProperty(Required = Required.Always)]
    public ulong CountOfBs { get; set; }
    [JsonProperty(Required = Required.Always)]
    public ulong TotalCount { get; set; }
    [JsonProperty(Required = Required.Always)]
    [JsonConverter(typeof(SomeCustomTypeJsonConverter))]
    public SomeCustomType SomeOtherField { get; set; }

    [JsonModelValidation]
    public bool IsValid() => CountOfAs + CountOfBs == TotalCount; 
}

因此,每次ABTest实例被反序列化时,我们要验证A组中的人数加上B组中的人数等于参加测试的总人数。

如何在JSON.Net中表达它?外部方法不太适合,因为可以在多个层次结构的任何位置找到此模型。因此,不能仅通过两个单独的步骤对它进行反序列化和验证。而且,我并没有真正将反序列化的对象置于可能无效的状态,因此它应该是默认反序列化的一部分。

1 个答案:

答案 0 :(得分:2)

如果您不希望该对象处于可能无效的状态,那么我首先建议使其变为不可变的。

然后您可以使用JsonConstructor进行验证:

public class ABTest
{
    [JsonProperty(Required = Required.Always)]
    public ulong CountOfAs { get; }

    [JsonProperty(Required = Required.Always)]
    public ulong CountOfBs { get; }

    [JsonProperty(Required = Required.Always)]
    public ulong TotalCount { get; }

    [JsonProperty(Required = Required.Always)]
    [JsonConverter(typeof(SomeCustomTypeJsonConverter))]
    public SomeCustomType SomeOtherField { get; set; }

    [JsonConstructor]
    public ABTest(ulong countOfAs, ulong countOfBs, ulong totalCount, SomeCustomType someOtherField)
    {
        if (totalCount != countOfAs + countOfBs)
            throw new ArgumentException(nameof(totalCount));

        CountOfAs = countOfAs;
        CountOfBs = countOfBs;
        TotalCount = totalCount;
        SomeOtherField = someOtherField;
    }
}

这为您提供了一个单一的构造函数,Json.NET和代码库的其余部分都可以使用该构造函数进行验证。