当反序列化到具有 json 字符串中不存在的枚举 属性 的模型时,强制 System.Text.Json 失败

Forcing System.Text.Json to fail when deserializing to a model with an enum property which is absent from the json string

我希望以下模型的反序列化失败:

class ExampleModel
{
    public ExampleEnum ExampleEnum { get; set; }

    public string ExampleString { get; set; }
}

enum ExampleEnum
{
    Value1,
    Value2,
}

ExampleEnum 的值未明确指定时,即:

{
    "ExampleString " : "abc"
}

它似乎回落到默认枚举的值,嗯,默认值:

string json = "{ \"exampleString\" : \"abc\" }";
var model = JsonSerializer.Deserialize<ExampleModel>(json);
Console.WriteLine(model.ExampleEnum); // outputs "Value1"

是否可以更改行为?

不幸的是,我没有找到一个简单的方法来做到这一点。与 newtonsoft.json 不同,system.text.json 没有内置此功能。唯一的方法似乎是编写自定义转换器。

您的自定义转换器代码应如下所示。

public class ExampleModelRequiredPropertyConverter : JsonConverter<ExampleModel>
{
    public override ExampleModel Read(ref Utf8JsonReader reader,Type type,JsonSerializerOptions options)
    {
        ExampleModel model = JsonSerializer.Deserialize<ExampleModel>(ref reader);
        
        if (model.ExampleEnum == default)
        {
            throw new JsonException("Required property not received in the JSON");
        }
        return model;
    }
    
    public override void Write(Utf8JsonWriter writer,ExampleModel model, JsonSerializerOptions options)
    {
        JsonSerializer.Serialize(writer, model);
    }
}

定义转换器后,您需要 add the converter 到 JsonSerializerOptions.Converters 集合以便它被注册。您不能将此转换器注册为属性,因为这会导致 Stack Overflow 异常。

如果您想将转换器用作属性,这些是 Microsoft 文档中定义的替代方法 here。该文档还讨论了上述方法。