Jackson 序列化:忽略空值(或 null)

Posted

技术标签:

【中文标题】Jackson 序列化:忽略空值(或 null)【英文标题】:Jackson serialization: ignore empty values (or null) 【发布时间】:2013-04-11 23:07:08 【问题描述】:

我目前使用的是 jackson 2.1.4,在将对象转换为 JSON 字符串时忽略字段时遇到了一些问题。

这是我的类,它充当要转换的对象:

public class JsonOperation 

public static class Request 
    @JsonInclude(Include.NON_EMPTY)
    String requestType;
    Data data = new Data();

    public static class Data 
        @JsonInclude(Include.NON_EMPTY)
        String username;
        String email;
        String password;
        String birthday;
        String coinsPackage;
        String coins;
        String transactionId;
        boolean isLoggedIn;
    


public static class Response 
    @JsonInclude(Include.NON_EMPTY)
    String requestType = null;
    Data data = new Data();

    public static class Data 
        @JsonInclude(Include.NON_EMPTY)
        enum ErrorCode  ERROR_INVALID_LOGIN, ERROR_USERNAME_ALREADY_TAKEN, ERROR_EMAIL_ALREADY_TAKEN ;
        enum Status  ok, error ;

        Status status;
        ErrorCode errorCode;
        String expiry;
        int coins;
        String email;
        String birthday;
        String pictureUrl;
        ArrayList <Performer> performer;
    


我是这样转换的:

ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

JsonOperation subscribe = new JsonOperation();

subscribe.request.requestType = "login";

subscribe.request.data.username = "Vincent";
subscribe.request.data.password = "test";


Writer strWriter = new StringWriter();
try 
    mapper.writeValue(strWriter, subscribe.request);
 catch (JsonGenerationException e) 
    // TODO Auto-generated catch block
    e.printStackTrace();
 catch (JsonMappingException e) 
    // TODO Auto-generated catch block
    e.printStackTrace();
 catch (IOException e) 
    // TODO Auto-generated catch block
    e.printStackTrace();


Log.d("JSON", strWriter.toString())

这是输出:

"data":"birthday":null,"coins":null,"coinsPackage":null,"email":null,"username":"Vincent","password":"test","transactionId":null,"isLoggedIn":false,"requestType":"login"

我怎样才能避免那些空值?我只想为“订阅”目的获取所需信息!

这正是我正在寻找的输出:

"data":"username":"Vincent","password":"test","requestType":"login"

我也尝试了@JsonInclude(Include.NON_NULL) 并将我的所有变量都设置为空,但它也不起作用!谢谢你们的帮助!

【问题讨论】:

How to tell Jackson to ignore a field during serialization if its value is null?的可能重复 【参考方案1】:

您将注释放在错误的位置 - 它需要在类上,而不是在字段上。即:

@JsonInclude(Include.NON_NULL) //or Include.NON_EMPTY, if that fits your use case 
public static class Request 
  // ...

如 cmets 中所述,在 2.x 以下版本中,此注解的语法为:

@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) // or JsonSerialize.Inclusion.NON_EMPTY

另一种选择是直接配置ObjectMapper,只需调用 mapper.setSerializationInclusion(Include.NON_NULL);

(为了记录,我认为这个答案的受欢迎程度表明这个注释应该在逐个字段的基础上适用,@fasterxml)

【讨论】:

真的没有办法让 include.NON_NULL 注释起作用吗?还是 NON_EMTPY ?因为我知道哪一个会是空的,但这取决于情况。我对要序列化/反序列化的每个对象都使用相同的“JsonOperation”类,并且我只根据情况初始化需要使用的变量。这是一个好方法还是我应该做几个只包含我需要的变量的类(这样我就不必使用任何注释,因为永远不会有空/空变量) 语法在最新版本中已更改为 @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) 和 @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY 如果你需要非空和非空,使用@JsonSerialize(include = JsonSerialize.Inclusion.NON_DEFAULT) 在课前或属性前使用 @JsonSerialize(include=Inclusion.NON_NULL) ...... @drewmoore 请再次检查,@JsonInclude(JsonSerialize.Inclusion.NON_NULL) 应该是@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL),这也是旧的弃用方式。所以你应该写“在低于 2.x 的版本中”,而不是“在 2.x+ 版本中” 2.+ 使用@JsonInclude(Include.NON_NULL)【参考方案2】:

你也可以设置全局选项:

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

【讨论】:

【参考方案3】:

你也可以尝试使用

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

如果您正在处理版本低于 2+ (1.9.5) 的 jackson,我对其进行了测试,您可以轻松地在类上方使用此注释。不为属性指定,只为类声明。

【讨论】:

JsonSerialize 的 include 属性已弃用,取而代之的是 JsonInclude 就像我说的:杰克逊版本低于 2+ (1.9.5) 问题询问特定版本 2.1.4【参考方案4】:

您需要添加import com.fasterxml.jackson.annotation.JsonInclude;

添加

@JsonInclude(JsonInclude.Include.NON_NULL)

在 POJO 之上

如果你有嵌套的 POJO 那么

@JsonInclude(JsonInclude.Include.NON_NULL)

需要添加每个值。

注意: JAXRS (Jersey) 在 2.6 及更高版本中自动处理此场景。

【讨论】:

在使用旧的 org.codehaus.jackson.annotate 包时是否有类似的功能? 是的,您可以在 getter 方法示例的顶部添加私有 int id; @JsonIgnore public int getId() return id; 与现有答案相同【参考方案5】:

对于杰克逊 2.x

@JsonInclude(JsonInclude.Include.NON_NULL)

就在场地之前。

【讨论】:

与现有答案相同【参考方案6】:

我最近在使用 2.6.6 版时遇到了类似的问题。

@JsonInclude(JsonInclude.Include.NON_NULL)

在归档或类级别上使用上述注释未按预期工作。 POJO 在我应用注释的地方是可变的。当我将 POJO 的行为更改为不可变时,注释就发挥了它的魔力。

我不确定这个库的新版本或以前版本是否有类似的行为,但对于 2.6.6,你当然需要有不可变 POJO 才能使注释工作。

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

在 ObjectMapper 中直接在全局级别设置序列化包含的各种答案中提到的上述选项也有效,但我更喜欢在类或文件级别控制它。

因此,如果您希望在 JSON 序列化时忽略所有空字段,则在类级别使用注释,但如果您只想在类中忽略少数字段,则在这些特定字段上使用它。如果您想更改特定响应的行为,这种方式更具可读性且易于维护。

【讨论】:

【参考方案7】:

或者您可以使用 GSON [https://code.google.com/p/google-gson/],其中这些空字段将被自动删除。

SampleDTO.java

public class SampleDTO 

    String username;
    String email;
    String password;
    String birthday;
    String coinsPackage;
    String coins;
    String transactionId;
    boolean isLoggedIn;

    // getters/setters

Test.java

import com.google.gson.Gson;

public class Test 

    public static void main(String[] args) 
        SampleDTO objSampleDTO = new SampleDTO();
        Gson objGson = new Gson();
        System.out.println(objGson.toJson(objSampleDTO));
    

输出:

"isLoggedIn":false

我使用 gson-2.2.4

【讨论】:

【参考方案8】:

如果您想从序列化中排除布尔类型,下面的代码可能会有所帮助:

@JsonInclude(JsonInclude.Include.NON_ABSENT)

【讨论】:

与现有答案相同

以上是关于Jackson 序列化:忽略空值(或 null)的主要内容,如果未能解决你的问题,请参考以下文章

让springboot序列化空值null为"null"而不是空报文体(jackson)

当值为“null”时,Jackson 忽略自定义字段反序列化器

Jackson 序列化 - 忽略未设置的值,但提供明确设置为 null 的值

详解jackson注解(三)jackson包含属性、忽略属性的注解

反序列化 null 值以使用 Jackson 枚举

Jackson怎样可以把null的属性转换为空字符