当前位置: 首页 > 知识库问答 >
问题:

配置Jackson以支持自定义序列化程序类的SerializationInclusion配置

全昊焜
2023-03-14

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

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

出于某种原因,当我调用RESTendpoint以获取包含上述示例值的Bar对象时,我看到了以下行为:

  • 序列化包含设置将应用于所有本身为空或空的属性(name, aList, obId)。
  • 序列化包含设置不被应用于任何由自定义序列化类设置为null的属性,并且我们返回具有null值的JSON。

我在这里的想法是,序列化器逻辑在Jackson已经从JSON中删除了所有空值和空值后被调用,因此“foo”属性被正确设置为空值,但没有被删除,因为包含逻辑已经执行。

有人对这里可能发生的事情有什么想法吗?在2.2.2版本中如何实现Jackson数据绑定库,这是一个怪癖吗?

杰克逊配置-

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

}

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

巴波乔-

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 
}

福波乔-

public abstract class Foo {

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

    // some getters and setters for the above properties
}

共有1个答案

程谦
2023-03-14

重写并实现JsonSerializer的isEmpty方法以实现您想要的。

定义定义什么

public boolean isEmpty(SerializerProvider provider, T value);

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

 类似资料:
  • 下面的代码再现了这个问题: 上面的代码不做其他注册“自定义”序列化程序的事情(只是委托回原始序列化程序),但它生成的JSON没有null属性: {“第一个”:“鲍勃”,“最后一个”:“巴克”} 我读过许多看似相关的SO文章,但没有一篇能让我找到解决方案。我尝试在序列化时显式地将映射器设置为,但没有成功。 我唯一的线索是JavaDoc for JsonSerializer中的一条注释: 注意:永远不

  • 情况如下:我已经设法让Jackson反序列化以下通用 作为HTTP客户端,并使用exchange

  • 我需要对一个长而复杂的json进行反序列化,为此我编写了一组java类来映射数据,并且我必须为许多不同类型的字段(包括String、Boolean、BigDecimal等)编写自定义反序列化器。 我知道我可以用相应的自定义反序列化器注释java类中的所有字段(如下所示),但是我需要注释所有类中的几乎所有字段。 或者可以通过某种方式为类实现自定义反序列化,该类定义如何根据每个字段的数据类型反序列化每

  • 我试图创建会影响序列化值的自定义jackson注释。 意思是: 现在序列化对象X(10)将导致: 我怎样才能做到这一点?

  • 我有一个Spring项目,我尝试添加一个自定义反序列化器来反序列化日期属性,具体取决于它们的格式。如果我将其用作Date属性的注释,则效果很好。但是,如果我将反序列化器添加到对象映射器中,当Jackson反序列化日期时,它不会调用。 我尝试这样应用我的自定义反序列化程序: 我不想每次都对Date属性应用注释,我想默认使用此反序列化器。我做错了什么?

  • 问题内容: 我是使用杰克逊图书馆的新手。 我正在尝试执行此操作(请参见下文),并且抛出错误。 例外: 39)): was expecting double-quote to start field name at [Source: java.io.StringReader@1afd1810; line: 1, column: 3] at org.codehaus.jackson.JsonParse