I want to deserialize some boolean values that I get in a JSON. The problem is that those values can be null, true, false, "true", false, "Y" or "N".
I've created my own boolean deserializer
public class CustomBooleanDeserializer extends JsonDeserializer<Boolean> {
final protected Class<?> _valueClass = Boolean.class;
@Override
public Boolean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
JsonProcessingException {
return _parseBooleanPrimitive2(jp, ctxt);
}
protected final boolean _parseBooleanPrimitive2(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
LogUtils.d("PARSE BOOLEAN");
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_TRUE) {
return true;
}
if (t == JsonToken.VALUE_FALSE) {
return false;
}
if (t == JsonToken.VALUE_NULL) {
return false;
}
if (t == JsonToken.VALUE_NUMBER_INT) {
return (jp.getIntValue() != 0);
}
if (t == JsonToken.VALUE_STRING) {
String text = jp.getText().trim();
if ("true".equals(text)) {
return true;
}
if ("false".equals(text) || text.length() == 0) {
return Boolean.FALSE;
}
if ("N".equalsIgnoreCase(text) || text.length() == 0) {
return Boolean.FALSE;
}
if ("Y".equalsIgnoreCase(text)) {
return Boolean.TRUE;
}
throw ctxt.weirdStringException(_valueClass, "only \"true\" or \"false\" recognized");
}
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass);
}
However, this deserializer is never called if I register it as this:
Version version = new Version(1, 0, 0, "SNAPSHOT");
SimpleModule module = new SimpleModule("MyModuleName", version);
module = module.addDeserializer(new CustomBooleanDeserializer());
objectMapper.registerModule(module);
If, on the other hand, I use @JsonDeserialize(using = CustomBooleanDeserializer.class) for the boolean fields, it does get called and works great. The only problem is that if the property is null, I get this exception:
org.codehaus.jackson.map.JsonMappingException: Problem deserializing property 'show_query_cond' (expected type: [simple type, class boolean]; actual type: [NULL]), problem: invalid value for field (through reference chain: com.csf.model.CSTable["show_query_cond"])
So, if the boolean property is null, my deserializer doesn't get a chance to run. Also, I tried using mapper.configure(DeserializationConfig.Feature.FAIL_ON_NULL_FOR_PRIMITIVES, false); but the exception is still thrown if I use the @JsonDeserialize annotation.
Does anyone know how to make this work?
As to registration, this is probably due to Java having both primitive boolean and Object wrapper Boolean. So you need to registed it using both java.lang.Boolean and Boolean.TYPE -- latter is the placeholder class for primitive type.
Null handling is different issue: deserialization method is not called for them. However, there is method
JsonDeserializer.getNullValue()
that should be called; and for primitives you must then just return 'Boolean.FALSE', since you can not assign null to a primitive value (it is ok to return wrapped; it gets properly handled).
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