2013-04-18 69 views
95

我目前正在使用杰克逊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,但它也不能工作!谢谢你们的帮助!

回答

178

你在错误的地方注释 - 它需要在班上,而不是在现场。即:

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

(有记录的,我认为这个答案的受欢迎程度表示这个注释应该是可以逐字段应用* ahem @faste RXML *)

+0

确实没有办法使include.NON_NULL注释生效?还是NON_EMTPY呢? 因为我知道哪一个是空的,但这取决于情况。我为每个想要序列化/反序列化的对象使用相同的“JsonOperation”类,我只根据情况初始化需要使用的变量。这是一个好办法,或者我应该做几个只包含我需要的变量的类(这样我就不必使用任何注释,因为永远不会有空/空变量) – Shinnyx

+0

Ahhh对不起,我看看现在发生了什么。看到我编辑的答案。 – drewmoore

+0

得到它的工作!我不能相信这是问题......谢谢你! – Shinnyx

40

您还可以设置全局选项:

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 
13

你也可以尝试使用

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) 

,如果你正在处理杰克逊低于版本2+(1.9.5 )我测试了它,你可以很容易地在课堂上面使用这个注释。不用于为属性指定,仅用于类别删除。

+1

包括JsonSerialize属性被弃用JsonInclude – fd8s0

+2

赞成像我说的:与杰克逊版本低于2+ 1.9.5) – erhan

+0

问题询问特定版本2.1.4 – fd8s0

3

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

OUTPUT:

{"isLoggedIn":false} 

我用GSON-2.2。4

+0

实际上该项目现在使用GSON。杰克逊没什么问题,但很少有Android相关的bug在我的个人经历中使用GSON解决了。感谢您的输入! Upvoted。 – Shinnyx

5

杰克逊2.x的

@JsonInclude(JsonInclude.Include.NON_NULL)只是前场。

9

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

对POJO

的顶部添加

@JsonInclude(JsonInclude.Include.NON_NULL) 

如果您有嵌套POJO然后

@JsonInclude(JsonInclude.Include.NON_NULL) 

需要在每个值添加。

注: JAXRS(新泽西州)自动处理这种情况2.6及以上。

+0

使用旧的org.codehaus.jackson.annotate包时有没有类似的功能? – pkran

+0

是的,你可以添加getter方法的示例private int id; @JsonIgnore public int getId(){ return id; } –

2

我最近有与2.6.6版类似的问题。

@JsonInclude(JsonInclude.Include.NON_NULL) 

使用上述注释无论是在提交还是在类别级别都没有按预期工作。 POJO在应用注释的地方是可变的。当我将POJO的行为改变为不可变时,注解发挥了神奇的作用。

我不知道如果到新的版本或该LIB之前的版本有类似的行为,但肯定2.6.6你需要有不可变的POJO的注释工作。

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 

以上直接在全球一级ObjectMapper设置系列化包容各种答案中提到选项的工作很好,但我更喜欢在类或提起水平控制它。

所以,如果你想所有的空字段被忽略,而JSON序列化,然后使用注释在类的水平,但如果你只想要几个字段在类忽略然后用它在这些具体领域。这样,如果您想更改特定响应的行为,便于维护,因此更易于读取&。

0

可以实现2种方式:

  1. 标记POJO到忽略空/空属性

    import com.fasterxml.jackson.annotation.JsonInclude 
    
    @JsonInclude(Include.NON_NULL) // or @JsonInclude(Include.NON_EMPTY) 
    
  2. 配置ObjectMapper序列化,如下POJO/JSON:

    import com.fasterxml.jackson.annotation.JsonInclude; 
    import com.fasterxml.jackson.databind.ObjectMapper; 
    
    ObjectMapper mapper = new ObjectMapper();    
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 
    
0

ç如果你想从序列化中排除布尔类型,ode bellow可能会有帮助:

@JsonInclude(JsonInclude.Include.NON_ABSENT)