如何使用Jackson对NULL值而不是空值进行JSON序列化? [英] How to JSON serialize null values but not empty values with Jackson?

查看:301
本文介绍了如何使用Jackson对NULL值而不是空值进行JSON序列化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Jackson ObjectMapper的一项功能允许删除空值:

There is a feature of Jackson ObjectMapper which allows empty values to be removed:

class Car {
   Optional<String> ownerName;
   String manufacturer;

   public Optional<String> getOwnerName() { return ownerName; }
   public String getManufacturer() { return manufacturer; }
}

Car batMobile = new Car();
batMobile.owner = Optional.of("Batman");
batMobile.manufacturer = null;

Car stolenCar = new Car();
stolenCar.owner = Optional.empty();
stolenCar.manufacturer = "Tesla";

ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_ABSENT);

mapper.writeValueAsString(batMobile);
/*
{
  "ownerName": "Batman"
}
*/
mapper.writeValueAsString(stolenCar);
/*
{
  "manufacturer": "Tesla"
}
*/

我想要的是删除Optional.empty值,但保留null值:

What I want instead is for Optional.empty values to be removed, but null values to remain:

mapper.writeValueAsString(batMobile);
/*
{
  "ownerName": "Batman",
  "manufacturer": null
}
*/
mapper.writeValueAsString(stolenCar);
/*
{
  "manufacturer": "Tesla"
}
*/

我希望这可以在全球范围内应用而无需DTO上的任何注释.

And I want this to apply globally without needing any annotations on the DTOs.

推荐答案

如果使用java.util.Optional,请确保已注册com.fasterxml.jackson.datatype.jdk8.Jdk8Module模块,该模块提供了额外的序列化器和反序列化器.

In case you use java.util.Optional be sure you have registered com.fasterxml.jackson.datatype.jdk8.Jdk8Module module which provides extra serialisers and deserialisers.

在您的情况下,最简单的方法是在属性级别上使用注释:

In your case the simplest way would be to use annotation on property levels:

class Car {

    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    Optional<String> ownerName;

    @JsonInclude
    String manufacturer;

    //getters, setters
}

默认值为Include.ALWAYS,应根据情况使用.

Default value is Include.ALWAYS which should be used in your case.

如果要全局执行此操作,则需要实现自定义过滤器并手动检查所有情况.简单的例子:

If you want to do that globally you need to implement custom filter and check all cases manually. Simple example:

class CustomFilter {

    @Override
    public boolean equals(Object obj) {
        // return false to keep value in response
        // return true to filter out value from response
        if (obj == null) {
            return false;
        }
        if (obj instanceof Optional) {
            Optional opt = (Optional) obj;
            return !opt.isPresent();
        }
        //other cases if needed

        return false;
    }
}

您可以按以下方式注册它:

You can register it as below:

ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.registerModule(new Jdk8Module());
mapper.setDefaultPropertyInclusion(JsonInclude.Value.construct(JsonInclude.Include.CUSTOM, JsonInclude.Include.CUSTOM, CustomFilter.class, CustomFilter.class));

以防万一,这不是您想要的,您需要全局设置最合适的值,并为给定的属性设置另一个值.如果您不能修改DTO类,则可以始终使用MixIn功能.

In case, this is not what you wanted you need to set globally most appropriate value and for given properties set another value. If you can not modify DTO classes, you can always use MixIn feature.

这篇关于如何使用Jackson对NULL值而不是空值进行JSON序列化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆