问题
I have a JSON
object with a Boolean
property that needs to allow only true
or false
during the deserialization.
Any value different of true
and false
should throw an exception.
How can I do that?
e.g.:
Valid json:
{
"id":1,
"isValid":true
}
Invalid json:
{
"id":1,
"isValid":1
}
Update
I tried what @Michał Ziober proposed and it worked fine.
As I'm implementing a Spring application (with Webflux) I just had to configure in a different way. I'm posting here what I did:
- Create a Configuration class extending from
DelegatingWebFluxConfiguration
- Override the
configureHttpMessageCodecs
method setting the property onObjectMapper
@Configuration
public class JacksonConfig extends DelegatingWebFluxConfiguration {
@Override
protected void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(MapperFeature.ALLOW_COERCION_OF_SCALARS);
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
configurer.defaultCodecs()
.jackson2JsonDecoder(new Jackson2JsonDecoder(objectMapper));
}
}
回答1:
You need to disable ALLOW_COERCION_OF_SCALARS feature:
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
mapper.disable(MapperFeature.ALLOW_COERCION_OF_SCALARS);
System.out.println(mapper.readValue(jsonFile, Pojo.class));
}
}
class Pojo {
private int id;
private Boolean isValid;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Boolean getIsValid() {
return isValid;
}
public void setIsValid(Boolean valid) {
isValid = valid;
}
@Override
public String toString() {
return "Pojo{" +
"id=" + id +
", isValid=" + isValid +
'}';
}
}
Above code prints:
Exception in thread "main"
com.fasterxml.jackson.databind.exc.MismatchedInputException
: Cannot coerce Number (1) for typejava.lang.Boolean
(enableMapperFeature.ALLOW_COERCION_OF_SCALARS
to allow) at [Source: (File); line: 3, column: 14] (through reference chain: Pojo["isValid"]) at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
回答2:
Well, it's not a for-any-case implementation, but may be it'll be suitable for you:
public class TestBooleanDeserializer extends JsonDeserializer<Boolean> {
@Override
public Boolean deserialize(JsonParser jsonParser, DeserializationContext context)
throws IOException, JsonProcessingException {
String str = jsonParser.getText();
boolean val = Boolean.valueOf(str);
if (!val && Objects.nonNull(str) && !Objects.equals("false", str.toLowerCase())) {
throw new RuntimeException("invalid JSON");
}
return val;
}
}
Since a Boolean.valueOf
is a result of check of the java.lang.Boolean#
public static boolean parseBoolean(String s) {
return ((s != null) && s.equalsIgnoreCase("true"));
}
here: boolean val = Boolean.valueOf(str);
you'll check is it a true
value or not. If not, you should check is it null
or false
: if (!val && Objects.nonNull(str) && !Objects.equals("false", str.toLowerCase()))
if it's not you can throw an exception whatever you need. Otherwise you'll return a boolean value
来源:https://stackoverflow.com/questions/57778322/jackson-is-there-a-way-to-ignore-0-1-on-boolean-deserialization