Jackson serialization: bỏ qua các giá trị trống (hoặc null)


138

Tôi hiện đang sử dụng jackson 2.1.4 và tôi gặp một số khó khăn khi bỏ qua các trường khi tôi chuyển đổi một đối tượng thành chuỗi JSON.

Đây là lớp của tôi hoạt động như đối tượng được chuyển đổi:

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;
    }
}
}

Và đây là cách tôi chuyển đổi nó:

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

Đây là đầu ra:

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

Làm thế nào tôi có thể tránh những giá trị null? Tôi chỉ muốn lấy thông tin cần thiết cho mục đích "đăng ký"!

Đây chính xác là đầu ra mà tôi đang tìm kiếm:

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

Tôi cũng đã thử @JsonInclude (Bao gồm.NON_NULL) và đặt tất cả các biến của tôi thành null, nhưng nó cũng không hoạt động! Cảm ơn sự giúp đỡ của các bạn!


Câu trả lời:


247

Bạn có chú thích ở sai vị trí - nó cần phải ở trên lớp, không phải trên trường. I E:

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

Như đã lưu ý trong các nhận xét, trong các phiên bản bên dưới 2.x cú pháp cho chú thích này là:

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

Tùy chọn khác là cấu hình ObjectMappertrực tiếp, chỉ cần gọi mapper.setSerializationInclusion(Include.NON_NULL);

(đối với hồ sơ, tôi nghĩ rằng mức độ phổ biến của câu trả lời này là một dấu hiệu cho thấy chú thích này nên được áp dụng trên cơ sở từng lĩnh vực, @fasterxml)


Thực sự không có cách nào để làm cho chú thích.NON_NULL hoạt động? Hoặc một NON_EMTPY? Bởi vì tôi biết cái nào sẽ là null, nhưng nó phụ thuộc vào tình huống. Tôi đang sử dụng cùng một lớp "JsonOperation" cho mọi đối tượng mà tôi muốn tuần tự hóa / giải tuần tự hóa và tôi chỉ khởi tạo các biến mà tôi cần sử dụng tùy thuộc vào tình huống. Đây có phải là một cách tốt để làm điều đó hay tôi nên thực hiện các lớp severals chỉ chứa các biến mà tôi cần (theo cách đó tôi sẽ không phải sử dụng bất kỳ chú thích nào, vì sẽ không bao giờ có biến null / rỗng)
Shinnyx

26
Cú pháp đã thay đổi trong phiên bản gần đây nhất thành @JsonSerialize (bao gồm = JsonSerialize.In Loại.NON_NULL) và @JsonSerialize (bao gồm = JsonSerialize.Ininating.NON_EMPTY Nếu bạn cần cả hai giá trị không rỗng và không trống .In Loại trừ.NON_DEFAULT)
Maciej

1
Sử dụng @JsonSerialize (bao gồm = Bao gồm.NON_NULL) trước lớp hoặc trước tài sản mà nó hoạt động ...
swan

1
@drewmoore vui lòng kiểm tra lại, @JsonInclude(JsonSerialize.Inclusion.NON_NULL) nên @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)và đó cũng là cách không dùng nữa. vì vậy bạn nên viết "trong phiên bản dưới 2.x", chứ không phải "trong phiên bản 2.x +"
WestFarmer

2
2. + sử dụng@JsonInclude(Include.NON_NULL)
Honghe.Wu

48

Bạn cũng có thể đặt tùy chọn toàn cầu:

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

15

Ngoài ra, bạn có thể thử sử dụng

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

nếu bạn đang xử lý jackson với phiên bản dưới 2+ (1.9.5) tôi đã thử nghiệm nó, bạn có thể dễ dàng sử dụng chú thích này phía trên lớp. Không được chỉ định cho các thuộc tính, chỉ dành cho giải mã lớp.


2
bao gồm thuộc tính của JsonSerialize không dùng cho JsonInclude
fd8s0

2
như tôi đã nói: với jackson với phiên bản dưới 2+ (1.9.5)
erhanasikoglu

câu hỏi hỏi về một phiên bản cụ thể 2.1.4
fd8s0

14

Bạn cần phải thêm import com.fasterxml.jackson.annotation.JsonInclude;

Thêm vào

@JsonInclude(JsonInclude.Include.NON_NULL)

trên đỉnh POJO

Nếu bạn đã lồng POJO rồi

@JsonInclude(JsonInclude.Include.NON_NULL)

cần thêm vào mọi giá trị

LƯU Ý: JAXRS (Jersey) tự động xử lý tình huống này 2.6 trở lên.


Có chức năng tương tự khi sử dụng gói org.codehaus.jackson.annotate cũ không?
pkran

Có, bạn có thể thêm vào đầu ví dụ phương thức getter private id id; @JsonIgnore công khai int getId () {return id; }
vaquar khan

1
Giống như câu trả lời hiện có
Karl Richter

4

Đối với jackson 2.x

@JsonInclude(JsonInclude.Include.NON_NULL)

ngay trước cánh đồng.


2
Giống như câu trả lời hiện có
Karl Richter

2

Gần đây tôi đã gặp vấn đề tương tự với phiên bản 2.6.6.

@JsonInclude(JsonInclude.Include.NON_NULL)

Sử dụng chú thích ở trên hoặc ở cấp độ nộp hoặc lớp không hoạt động như mong đợi. POJO có thể thay đổi khi tôi áp dụng chú thích. Khi tôi thay đổi hành vi của POJO thành bất biến, chú thích đã phát huy tác dụng kỳ diệu của nó.

Tôi không chắc liệu phiên bản mới hoặc phiên bản trước của lib này có hành vi tương tự hay không nhưng đối với 2.6.6 chắc chắn bạn cần phải có POJO bất biến để chú thích hoạt động.

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

Tùy chọn trên được đề cập trong các câu trả lời khác nhau về cài đặt tuần tự hóa trong ObjectMapper trực tiếp ở cấp độ toàn cầu cũng hoạt động, nhưng, tôi thích kiểm soát nó ở cấp độ hoặc cấp độ nộp đơn.

Vì vậy, nếu bạn muốn tất cả các trường null bị bỏ qua trong khi tuần tự hóa JSON thì hãy sử dụng chú thích ở cấp lớp nhưng nếu bạn chỉ muốn vài trường bị bỏ qua trong một lớp thì hãy sử dụng nó trên các trường cụ thể đó. Bằng cách này, nó dễ đọc hơn và dễ bảo trì hơn nếu bạn muốn thay đổi hành vi cho phản ứng cụ thể.


2

Hoặc bạn có thể sử dụng GSON [ https://code.google.com.vn/p/google-gson/ ], trong đó các trường null này sẽ tự động bị xóa.

MẫuDTO.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));
    }
}

ĐẦU RA:

{"isLoggedIn":false}

Tôi đã sử dụng gson-2.2.4


-1

Mã dưới đây có thể giúp đỡ nếu bạn muốn loại trừ loại boolean khỏi tuần tự hóa:

@JsonInclude(JsonInclude.Include.NON_ABSENT)

1
Giống như câu trả lời hiện có
Karl Richter
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.