How to remove null values generated by a jackson custom serializer?

Viewed 1034

Given the following class:

@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Account {

    [... A lot of serialized properties]

    @JsonSerialize(nullsUsing = JacksonSpringSpelSerializer.class, using = JacksonSpringSpelSerializer.class)
    @JsonView(View.Contract.class)
    @Value("#{@contractService.getActiveContract(#this)}")
    public Contract activeContract;

}

Basically the property activeContract is null, and its value is evaluated only when the correct @JsonView is provided, the value is computed by a Spring Spel expression, everything is done in a custom Serializer JacksonSpringSpelSerializer.

Everything works as expected BUT the computed value can sometimes be null, which is normal, and I end up with a json like this:

{
    [... All properties],
    "activeContract": null
}

The issue is that I don't want null properties to be in the returned json, the @JsonInclude(JsonInclude.Include.NON_EMPTY) is ignored when a custom serializer is set on a property.

After digging a bit, I found out that the custom serializer is called by BeanPropertyWriter.serializeAsField() that contains:

    if (value == null) {
        if (_nullSerializer != null) {
            gen.writeFieldName(_name);
            _nullSerializer.serialize(null, gen, prov);
        }
        return;
    }

So the name of the field is written by gen.writeFieldName(_name); before the custom serializer is actually called, and I didn't find a proper way to prevent this behavior or to remove the null properties generated by the custom Serializer.

Is there a proper way to achieve such a result ? Any advice would be very welcome :D

Thanks <3

3 Answers

you can try use JsonInclude.Include.NON_NULL, like the follow code

@JsonInclude(JsonInclude.Include.NON_NULL)

If you already specified Include.NON_EMPTY in some way either globally or on the field, you have to also override com.fasterxml.jackson.databind.JsonSerializer#isEmpty(com.fasterxml.jackson.databind.SerializerProvider, T)

static class Serializer extends JsonSerializer<Foo> {

    @Override
    public void serialize(Foo value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        // serialize
    }

    @Override
    public boolean isEmpty(SerializerProvider provider, Foo value) {
        // this will be called for Include.NON_EMPTY
        boolean isItEmpty = // get it somehow
        return isItEmpty;
    }
}

This can be fixed by adding the include attribute in the annotation:

 @JsonSerialize(using=JacksonSpringSpelSerializer.class, include=JsonInclude.NON_NULL)

The field level default for this in JsonSerialize is ALWAYS, which overrides the class level setting, hence the undesired behavior.

Related