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.
The default value of the bool type is false .
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.
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.
A bool expresses a truth value. It can be either true or false .
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());});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With