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
booleanand Object wrapperBoolean. So you need to registed it using bothjava.lang.BooleanandBoolean.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
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).