避免将任何数字绑定到 bool 属性

Я T*_*bur 5 c# asp.net-web-api asp.net-core asp.net-core-webapi

我有简单的 ASP.NET Core WebApi 模型

public class Model
{
    public bool? Value {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

和端点

[HttpPost]
public async Task<IActionResult> Create([FromBody] Model model)
Run Code Online (Sandbox Code Playgroud)

当我用 body 发出 POST 请求时

{
   "Value" : 7676
}
Run Code Online (Sandbox Code Playgroud)

或者

{
   "Value" : 2955454545645645645645645645654534534540    
}
Run Code Online (Sandbox Code Playgroud)

然后 model.Value == true

如何避免这种情况?在这种情况下我需要一些错误,因为7676不是布尔值。

我发现了this questionthis,但解决方案不适合我,因为我在不同的项目中有很多模型(因此,很难将JsonConverter属性从答案添加到所有属性)

此外,我正在寻找任何描述此行为的文档。

Sha*_*hat 5

您可以通过创建自定义 JsonConverter 来实现它。可以在此处找到相同的文档

这种行为的原因与 JSON.NET 或System.Text.JSON反序列化类型的方式有关。由于123可以转换为booleantrue,反序列化成功。它根据整数值认为它是真或假,直到您显式定义如下 JsonConverter 以检查正在读取的令牌实际上是布尔值。

如果您不使用 Newtonsoft。您可以使用System.Text.Json您可以按照此页面创建自定义 JSON 转换器

public class OnlyBoolean : JsonConverter
{
     readonly JsonSerializer defaultSerializer = new JsonSerializer();

     public override bool CanConvert(Type objectType)
     {
         return objectType == typeof(bool);
     }

     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
     {
         switch (reader.TokenType)
         {

             case JsonToken.Boolean:
             {
                 return defaultSerializer.Deserialize(reader, objectType);
             }
             case JsonToken.String:
             {
                 if (reader.Value?.ToString() == "true" || reader.Value?.ToString() == "false")
                      return defaultSerializer.Deserialize(reader, objectType);
                 else
                      throw new JsonSerializationException(string.Format("Token \"{0}\" of type {1} is not a boolean type", reader.Value, reader.TokenType));
            }
            case JsonToken.Integer:
            {
                if (Convert.ToInt32(reader.Value) == 1 || Convert.ToInt32(reader.Value) == 0)
                    return defaultSerializer.Deserialize(reader, objectType);
                else
                    throw new JsonSerializationException(string.Format("Token \"{0}\" of type {1} is not a boolean type", reader.Value, reader.TokenType));
            }
            default:
                      throw new JsonSerializationException(string.Format("Value\"{0}\" of type {1} is not a boolean type", reader.Value, reader.TokenType));
          }
      }

      public override bool CanWrite { get { return false; } }

      public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
      {
          throw new NotImplementedException();
      }
}
Run Code Online (Sandbox Code Playgroud)

然后将您的模型装饰为:

public class Model
{
    [JsonConverter(typeof(OnlyBoolean))]
    public bool? Value {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

或在 Startup 中全局注册

services.AddMvc().AddJsonOptions(options => { options.SerializerSettings.Converters.Add(new OnlyBoolean());});
Run Code Online (Sandbox Code Playgroud)