【问题标题】:Configure Jackson to honor SerializationInclusion configuration for custom Serializer classes配置 Jackson 以尊重自定义序列化程序类的 SerializationInclusion 配置
【发布时间】:2017-06-12 11:45:22
【问题描述】:

当自定义序列化程序类创建空字段时,试图让 Jackson 从结果 JSON 中正确删除空字段时遇到了一个相当有趣的问题。我已经非常彻底地搜索了有关 Serializer 和 SerializationInclusion 配置的信息,但我没有找到任何似乎可以解释我所看到的内容。

我有一个 Jackson 对象映射器,通过 Spring 配置和自动装配。对象映射器配置和 POJO(为简洁起见进行了编辑)看起来或多或少类似于下面的代码。

由于某种原因,当我调用我们的 REST 端点以获取包含上述示例值的 Bar 对象时,我看到以下行为:

  • SerializationInclusion 设置应用于所有本身为空或 null 的属性(名称、aList、objId)。
  • SerializationInclusion 设置未应用于任何由自定义 Serializer 类设置为 null 的属性,我们返回的 JSON 中存在 null 值。

我的想法是,在 Jackson 已经从 JSON 中删除所有 null 和空值之后调用 Serializer 逻辑,因此“foo”属性被正确设置为 null,但由于包含逻辑已被删除,因此不会被删除已经执行了。

有人对这里可能发生的事情有任何想法吗?这是在 2.2.2 版本中实现 Jackson-databind 库的一个怪癖吗?


杰克逊配置 -

@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;
}

自定义序列化器 -

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

}

对象模型看起来像这样(为简洁起见再次编辑,示例值设置在类成员上作为示例数据):

酒吧 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 -

public abstract class Foo {

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

    // some getters and setters for the above properties
}

【问题讨论】:

  • 我知道这已经过时了,但是你用自定义序列化器解决了这个问题吗?希望避免到处写支票...

标签: java json spring serialization jackson


【解决方案1】:

重写并实现JsonSerializer的isEmpty方法来实现你想要的。

对于什么是空的自定义定义,您的 JsonSerializer 实现需要覆盖此方法:

public boolean isEmpty(SerializerProvider provider, T value);

请注意,调用者在写入字段名称时必须处理过滤;只有在需要实际序列化时才会调用序列化程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2016-11-29
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-18
    相关资源
    最近更新 更多