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


138

我当前正在使用杰克逊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)并将所有变量都设置为null,但是它也不起作用!感谢您的帮助!


Answers:


247

您将注解放置在错误的位置-注解必须在类上,而不是在字段上。即:

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

如注释中所述,在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”类,并且仅根据情况初始化需要使用的变量。这是一个好方法吗?还是我应该做几个只包含我需要的变量的类(那样我就不必使用任何注释,因为永远不会有null / empty变量)
Shinnyx

26
语法在最新版本中已更改为@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)和@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY如果您同时需要非空和非空,请使用@JsonSerialize(include = JsonSerialize .Inclusion.NON_DEFAULT)
Maciej

1
在类之前或在属性起作用之前使用@JsonSerialize(include = Inclusion.NON_NULL)...
天鹅

1
@drewmoore,请再次检查, @JsonInclude(JsonSerialize.Inclusion.NON_NULL) 应该是@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL),这也是旧的弃用方式。所以您应该写“在2.x以下版本中”,而不是“在2.x +版本中”
WestFarmer

2
2. +使用@JsonInclude(Include.NON_NULL)
Honghe.Wu

48

您还可以设置全局选项:

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

15

您也可以尝试使用

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

如果您使用我测试过的版本低于2+(1.9.5)的杰克逊,则可以在类上方轻松使用此注释。不是为属性指定的,只是为类定义的。


2
JsonSerialize的include属性已弃用JsonInclude
fd8s0 2014年

2
就像我说的:杰克逊的版本低于2+(1.9.5)
erhanasikoglu 2014年

问题询问特定的版本2.1.4
fd8s0 2014年

14

您需要添加 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包时,是否有类似的功能?
pkran,2016年

是的,您可以在getter方法示例的顶部添加private int id;@JsonIgnore public int getId(){返回ID;}
vaquar khan

1
与现有答案相同
Karl Richter

4

对于杰克逊2.x

@JsonInclude(JsonInclude.Include.NON_NULL)

就在田野之前。


2
与现有答案相同
Karl Richter

2

我最近在版本2.6.6中遇到类似的问题。

@JsonInclude(JsonInclude.Include.NON_NULL)

在字段级别或类级别使用以上注释均无法按预期方式工作。POJO在我应用注释的地方是可变的。当我将POJO的行为更改为不可变时,注释发挥了神奇的作用。

我不确定该库的最新版本或先前版本是否具有类似的行为,但是对于2.6.6,您肯定需要具有不可变POJO才能使注释起作用。

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

在直接在全局级别将ObjectMapper设置为包含序列化的各种答案中提到的上述选项也可以使用,但我更喜欢在类或文件级别进行控制。

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


2

或者,您可以使用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


-1

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

@JsonInclude(JsonInclude.Include.NON_ABSENT)

1
与现有答案相同
Karl Richter
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.