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

176

我目前正在使用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)并将所有变量设置为null,但也没有起作用!谢谢大家的帮助!


8个回答

304

您的注释放错位置了——它应该放在类上,而不是字段上。例如:

@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)

31
最近版本的语法已更改为@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),它可以起作用... - sawan
3
@drewmoore请再次检查,@JsonInclude(JsonSerialize.Inclusion.NON_NULL) 应该改为 @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL),同时这是过时的写法。因此,你应该写成“在版本低于2.x的情况下”,而不是“在2.x+版本中”。 - WestFarmer
4
  1. 使用 @JsonInclude(Include.NON_NULL)
- Honghe.Wu
1
如果您想在字段中使用它,请使用@JsonInclude(JsonInclude.Include.NON_NULL)。 - thedrs
显示剩余6条评论

61

你也可以设置全局选项:

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

19

此外,你可以尝试使用

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

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


2
JsonSerialize 的 include 属性已被弃用,应使用 JsonInclude。 - fd8s0
2
就像我说的那样:使用Jackson版本低于2+(1.9.5)。 - erhanasikoglu
问题询问特定版本2.1.4。 - fd8s0

18

您需要添加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
是的,您可以在getter方法上方添加注释。例如: private int id; @JsonIgnore public int getId() { return id; } - vaquar khan
1
与现有答案相同。 - Kalle Richter

6

针对jackson 2.x

@JsonInclude(JsonInclude.Include.NON_NULL)

在该字段之前。

2
与现有答案相同。 - Kalle Richter

4

最近我遇到了与2.6.6版本类似的问题。

@JsonInclude(JsonInclude.Include.NON_NULL)

在字段或类级别使用上述注释并没有按预期工作。当我应用该注释时,POJO是可变的。当我将POJO的行为更改为不可变时,该注释起了作用。

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

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

在ObjectMapper中直接设置序列化包含选项的各种答案中提到的选项同样适用,但是我更喜欢在类或字段级别上进行控制。

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


1
以下代码可以帮助您在序列化时排除布尔类型: ```Java @JsonIgnoreProperties({ "fieldNameHere" }) public class ClassName { private boolean fieldNameHere; } ```
@JsonInclude(JsonInclude.Include.NON_ABSENT)

2
与现有答案相同。 - Kalle Richter

1

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接