IcedDante
IcedDante

Reputation: 6842

Avoid Serializing null fields with Jackson custom JsonSerializer and JsonGenerator

Jackson serialization to JSON has some nice features like SerializationFeature.WRITE_NULL_MAP_VALUES which allows you to avoid writing nulls into your serialized object.

However, if I use a custom JsonSerializer this setting is ignored and I'm forced to put null checks in all my calls to writeStringField. For example, I register a custom JsonSerializer:

ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(CloudDocument.class, new ImportProductSerializer());

objectMapper.registerModule(simpleModule);

and then inside of ImportProductSerializer I'm stuck with putting a null check for every field I want to serialize which gets ugly and tedious:

private class ImportProductSerializer extends JsonSerializer<CloudDocument> {
    @Override
    public void serialize(CloudDocument value, 
        JsonGenerator gen, //Customize this?
        SerializerProvider serializers) throws Exception {
        gen.writeStartObject();
        gen.writeStringField("type", "add");

        //Null check here and every other field: gross!
        if(StringUtils.hasText(importProduct.getExtraListingSku1())) { 
            gen.writeStringField("extralistingsku1", importProduct.getExtraListingSku1());
        }
        gen.writeEndObject();
    }
}

The solution I would like to employ is having my custom JsonSerializer use a custom JsonGenerator. The serialize method takes JsonGenerator in as a parameter and I could easily define it like so:

private class CustomGenerator extends JsonGenerator {

    @Override
    public JsonGenerator setCodec(ObjectCodec oc) {
        super.setCodec(oc);
    }


    @Override
    public void writeStringField(String fieldName, String value) throws IOException {
        if(value==null) return;
        super.writeStringField(fieldName.toLowerCase(), value);
    }
    .... //other methods implemented
}

but I'm not sure how to configure the ObjectMapper to use my implementation of CustomGenerator. The benefit of this approach is I could customize the writeField methods to do the null checks and to make sure that the field names subscribe to the naming conventions that are expected which, in this case, involve converting camelCase to lower_underscore.

Is there a way to configure the JsonGenerator that is instantiated with the call to objectMapper.writeValue()?

Upvotes: 0

Views: 4006

Answers (1)

StaxMan
StaxMan

Reputation: 116620

The question is bit open-ended, as I do not know exactly what you have tried so far; how much of the work is done by custom serializer. In general serializers are expected to delegate much of the handling to minimize amount of work they do.

But if you have defined a custom serializer to handle POJOs with included fields (instead of a custom serializer for something serialized as a JSON String, or other scalar values), yes, you do need to handle your own checks. This is partly because there are many ways to potentially change inclusion; not just SerializationFeature, but also @JsonFormat annotation for properties; there is no way to handle this transparently when delegating control to custom serializers.

So, yes, if you end up using writeStringField(), you do need to check for default inclusion settings and omit write appropriately.

Upvotes: 1

Related Questions