问题
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.
回答1:
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());});
来源:https://stackoverflow.com/questions/59470631/avoid-bind-any-number-to-bool-property