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

Posted

技术标签:

【中文标题】避免将任何数字绑定到布尔属性【英文标题】:Avoid bind any number to bool property 【发布时间】:2020-04-15 15:30:26 【问题描述】:

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

public class Model

    public bool? Value get; set;

和端点

[HttpPost]
public async Task<IActionResult> Create([FromBody] Model model)

当我使用正文发出 POST 请求时


   "Value" : 7676


   "Value" : 2955454545645645645645645645654534534540    

然后model.Value == true

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

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

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

【问题讨论】:

编写自定义模型绑定器并使用它 当您尝试发布无效的 Json 属性值时,您应该会收到类似“无法将 JSON 值转换为 System.Nullable`1[System.Boolean]。路径:$.Value”的错误。您使用的是哪个版本的 asp.net core? @vendettamit 是的,我也这么认为,但行为就像我描述的那样。 ASP.NET Core 2.2 @Milney 你能帮忙定制模型活页夹吗?我有很多模型,我可以为所有模型中的布尔属性创建活页夹吗?我试过这个docs.microsoft.com/en-us/aspnet/core/mvc/advanced/…,但总是得到ValueProviderResult.None 创建一个从JsonConverter派生的自定义MyBookConverter,然后注册services.AddMvc().AddJsonOptions(options =&gt; options.SerializerSettings.Converters.Add(new MyBoolConverter());); 【参考方案1】:

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

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

如果您不使用 Newtonsoft。你用System.Text.Json你可以关注这个页面create a custom JSON converter

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();
      

然后将模型装饰为:

public class Model

    [JsonConverter(typeof(OnlyBoolean))]
    public bool? Value get; set;

或在 Startup 中全局注册

services.AddMvc().AddJsonOptions(options =>  options.SerializerSettings.Converters.Add(new OnlyBoolean()););

【讨论】:

@Chebur 我已经编辑它以接受“true”“false”1 和 0 作为有效输入。这能回答你的问题吗? 很好的答案。你知道这是否有一个等效的 asp.net 框架吗?

以上是关于避免将任何数字绑定到布尔属性的主要内容,如果未能解决你的问题,请参考以下文章

JavaFX布尔绑定和TableView绑定多个

AngularJS:如何在为缺少的属性提供默认值时避免非分配错误?

数据绑定如何避免 WPF 中的递归更新?

Cocoa:如何将布尔属性绑定到 NSCellStateValue?

将用户控件绑定到布尔属性的对面

Delphi 中要避免的组件