Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson Ignores Custom Field Deserializer When Value is "null"

I wrote a custom deserializer for Jackson for a certain field (follows). I use it with this annotation:

@JsonDeserialize(using = TokenTypeDeserializer.class)
TokenType type;

It seems to work fine, as long as I pass a value in the field. When I started testing it, I passed the field with null as value. In this case it ignored my custom deserializer, skipped it and just put null as the value. It's a problem because I have a unique way of action when I get null in that field.

How can I force it to go through my custom deserializer when the value is null?

This is the custom deserializer I wrote:

public static class TokenTypeDeserializer extends StdDeserializer<TokenType> {

    public TokenTypeDeserializer() {
        this(null);
    }

    protected TokenTypeDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public TokenType deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        ObjectCodec oc = p.getCodec();
        JsonNode node = oc.readTree(p);
        String type = node.asText();

        TokenType tokenType = TokenType.getTokenTypeFromString(type);
        return tokenType;
    }
}

I looked a little bit into the ObjectMapper code, and saw this:

public final Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException
{
    JsonToken t = jp.getCurrentToken();
    if (t == JsonToken.VALUE_NULL) {
        return (_nullProvider == null) ? null : _nullProvider.nullValue(ctxt);
    }
    if (_valueTypeDeserializer != null) {
        return _valueDeserializer.deserializeWithType(jp, ctxt, _valueTypeDeserializer);
    }
    return _valueDeserializer.deserialize(jp, ctxt);
}

It seems that the ObjectMapper first checks if the value is null, and if thus the case, returns a default value. Any ideas on how to force it to go through my deserializer?

like image 957
Gil Shamgar Avatar asked Jul 09 '17 08:07

Gil Shamgar


1 Answers

According to this discussion, looks like you can't provide an alternative for null unless it's a primitive type (which can't be null).

All in all this is a common behavior, if you are deserializing a null value into a nullable type, null is the value you should get there.

like image 178
Moti Azu Avatar answered Sep 28 '22 03:09

Moti Azu