避免使用 Jackson 自定义 JsonSerializer 和 JsonGenerator 序列化空字段

Avoid Serializing null fields with Jackson custom JsonSerializer and JsonGenerator

Jackson 序列化到 JSON 有一些很好的特性,例如 SerializationFeature.WRITE_NULL_MAP_VALUES,它允许您避免将空值写入序列化对象。

但是,如果我使用自定义 JsonSerializer,则此设置将被忽略,我不得不在对 writeStringField 的所有调用中进行空值检查。例如,我注册了一个自定义的 JsonSerializer:

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

objectMapper.registerModule(simpleModule);

然后在 ImportProductSerializer 内部,我一直坚持对我想要序列化的每个字段进行空检查,这变得丑陋乏味:

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();
    }
}

我想采用的解决方案是让我的自定义 JsonSerializer 使用自定义 JsonGenerator。 serialize 方法将 JsonGenerator 作为参数,我可以像这样轻松定义它:

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
}

但我不确定如何配置 ObjectMapper 以使用我的 CustomGenerator 实现。这种方法的好处是我可以自定义 writeField 方法来执行 null 检查并确保字段名称订阅预期的命名约定,在这种情况下,涉及将 camelCase 转换为 lower_underscore.

有没有办法配置通过调用 objectMapper.writeValue() 实例化的 JsonGenerator?

这个问题有点开放性,因为我不知道你到目前为止到底做了什么;自定义序列化程序完成了多少工作。 一般而言,序列化程序应委托大部分处理以最大限度地减少它们所做的工作量。

但是,如果您已经定义了一个自定义序列化程序来处理包含字段的 POJO(而不是针对序列化为 JSON 字符串或其他标量值的内容的自定义序列化程序),是的,您确实需要处理你自己的支票。这部分是因为有很多方法可以潜在地改变包容性;不仅 SerializationFeature,还有 @JsonFormat 属性注释;将控制委托给自定义序列化程序时,无法透明地处理此问题。

所以,是的,如果您最终使用 writeStringField(),您确实需要检查默认包含设置并适当省略写入。