Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoid bind any number to bool property

I have simple ASP.NET Core WebApi with model

public class Model
{
    public bool? Value {get; set;}
}

and endpoint

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

When I make a POST request with body

{
   "Value" : 7676
}

or

{
   "Value" : 2955454545645645645645645645654534534540    
}

then model.Value == true

How to avoid this? I need some error in this case, because 7676 is not the Boolean value.

I found this question and this, but solution is not fit for me, because I have a many models in different projects (so, it will hard to add JsonConverter attribute, from answer, to all properties)

Also, I'm looking for any docs that describes this behavior.

like image 505
Я TChebur Avatar asked Dec 24 '19 15:12

Я TChebur


People also ask

Is bool false by default C#?

The default value of the bool type is false .

Are bools false by default?

The default value of Boolean is False . Boolean values are not stored as numbers, and the stored values are not intended to be equivalent to numbers.

What is bool property?

The value of a BooleanProperty can be get and set with ObservableBooleanValue. get() , BooleanExpression. getValue() , WritableBooleanValue. set(boolean) , and setValue(Boolean) . A property can be bound and unbound unidirectional with Property.

Does bool mean false?

A bool expresses a truth value. It can be either true or false .


1 Answers

You can achieve it by creating a custom JsonConverter. The documenation for the same can be found here

The reason for this behavior has got to do with the way JSON.NET or System.Text.JSON deserializes types. Since 123 can be converted to boolean true, deserialization is successful. It considers it to be true or false depending upon the integer value until you explicitly define a JsonConverter as below that checks the token being read is actually boolean.

If you aren't using Newtonsoft. You make use of System.Text.Json You can follow this page to 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();
      }
}

and then decorate your model as:

public class Model
{
    [JsonConverter(typeof(OnlyBoolean))]
    public bool? Value {get; set;}
}

or register it globally in Startup

services.AddMvc().AddJsonOptions(options => { options.SerializerSettings.Converters.Add(new OnlyBoolean());});
like image 174
Shahid Manzoor Bhat Avatar answered Sep 28 '22 10:09

Shahid Manzoor Bhat