简体   繁体   English

配置Jackson以遵循自定义序列化程序类的SerializationInclusion配置

[英]Configure Jackson to honor SerializationInclusion configuration for custom Serializer classes

I'm having a rather interesting problem attempting to get Jackson to properly remove null fields from resulting JSON when they have been created by a custom serializer class. 我有一个相当有趣的问题,试图让Jackson在自定义序列化程序类创建时,从生成的JSON中正确删除空字段。 I've searched pretty thoroughly for information regarding Serializer and the SerializationInclusion configuration, but I haven't found anything that seems to explain what I'm seeing. 我已经彻底搜索了有关Serializer和SerializationInclusion配置的信息,但我还没有发现任何似乎可以解释我所看到的内容。

I have a Jackson object mapper configured and autowired in via Spring. 我有一个Jackson对象映射器配置并通过Spring自动装配。 The object mapper configuration and POJOs (edited for brevity) look more or less like the code below. 对象映射器配置和POJO(为简洁起见编辑)看起来或多或少类似于下面的代码。

For some reason, when I call our REST endpoint to get a Bar object back that contains the above example values I see the following behavior: 出于某种原因,当我调用我们的REST端点来获取包含上述示例值的Bar对象时,我看到以下行为:

  • The SerializationInclusion setting is being applied to all properties that are empty or null on their own (name, aList, objId). SerializationInclusion设置正在应用于所有属性为空或自己为null(name,aList,objId)。
  • The SerializationInclusion setting is NOT being applied to any properties that are set to null by a custom Serializer class, and we get back JSON that has a null value present. SerializationInclusion设置未应用于由自定义Serializer类设置为null的任何属性,并且我们返回具有空值的JSON。

My thought here is that the Serializer logic gets called AFTER the Jackson has already removed all null and empty values from the JSON, and therefore the "foo" property is properly set to null, but is not removed because the inclusion logic has already executed. 我的想法是,在Jackson已经从JSON中删除了所有空值和空值之后调用Serializer逻辑,因此“foo”属性被正确设置为null,但由于包含逻辑已经执行,因此不会被删除。

Does anyone have any thoughts about what might be going on here? 有没有人对这里可能发生的事情有任何想法? Is this a quirk in how Jackson-databind library is implemented in version 2.2.2? 这是在2.2.2版本中如何实现Jackson-databind库的一个怪癖?


Jackson Config - 杰克逊配置 -

@Bean
public JacksonObjectMapper jacksonMapper() {
    final JacksonObjectMapper mapper = new JacksonObjectMapper();

    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    mapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
    mapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
    mapper.registerModule(agJacksonModule());

    return mapper;
}

@Bean
public SimpleModule agJacksonModule() {
    final SimpleModule module = new SimpleModule();

    module.addSerializer(Foo.class, new FooSerializer());

    return module;
}

Custom Serializer - 自定义序列化器 -

public class FooSerializer extends JsonSerializer<Foo> {

@Override
public void serialize(Sponsor sponsor, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
        throws IOException {

    // write null value for sponsor json property, if sponsor object has all empty or null fields
    if(sponsor == null || isObjectEmpty(sponsor)) {
        jsonGenerator.writeNull();
        return;
    }

    // write out object
    jsonGenerator.writeStartObject();
    jsonGenerator.writeStringField("imgUrl", sponsor.getImgUrl());
    jsonGenerator.writeStringField("clickUrl", sponsor.getClickUrl());
    jsonGenerator.writeStringField("sponsorName", sponsor.getSponsorName());
    jsonGenerator.writeStringField("sponsorText", sponsor.getSponsorText());
    jsonGenerator.writeEndObject();

}

private boolean isObjectEmpty(Sponsor sponsor) {
    return Strings.isNullOrEmpty(sponsor.getClickUrl())
            && Strings.isNullOrEmpty(sponsor.getImgUrl())
            && Strings.isNullOrEmpty(sponsor.getSponsorName())
            && Strings.isNullOrEmpty(sponsor.getSponsorText());
}

} }

The object model looks something like this (again edited for brevity, sample values are set on the class members as example data): 对象模型看起来像这样(为简洁起见,再次编辑,样本值在类成员上设置为示例数据):

Bar POJO - 酒吧POJO -

public abstract class Bar {

    protected Foo foo = aFoo;
    protected String name = "";
    protected ArrayList aList = Lists.newArrayList();
    protected String objId = null;

    // some getters and setters for the above properties 
}

Foo POJO - Foo POJO -

public abstract class Foo {

    protected String aString = "";
    protected String bString = "";
    protected String cString = "";
    protected String dString = "";

    // some getters and setters for the above properties
}

Override and implement the isEmpty method of JsonSerializer to achieve what you want. 覆盖并实现JsonSerializer的isEmpty方法以实现您想要的效果。

For custom definition of what emptymeans, your JsonSerializer implementation needs to override this method: 对于什么emptymeans的自定义定义,您的JsonSerializer实现需要覆盖此方法:

public boolean isEmpty(SerializerProvider provider, T value);

Note that it is the caller that has to handle filtering as it writes field name; 请注意,调用者在写入字段名称时必须处理过滤; serializer will only be called in case actual serialization is needed. 只有在需要实际序列化时才会调用序列化程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM