2013-01-16 35 views
7

Tôi cần thêm thuộc tính mới vào một đối tượng, khi tuần tự hóa thành JSON. Giá trị của thuộc tính được tính trên thời gian chạy và không tồn tại trong đối tượng. Ngoài ra, cùng một đối tượng có thể được sử dụng để tạo JSON khác nhau với các trường ot khác nhau (loại có một lớp cơ sở với các lớp con, nhưng tôi không muốn tạo các lớp chỉ để tạo JSON).Jackson :: thêm các trường bổ sung vào một đối tượng trong tuần tự hóa

Cách tốt nhất để thực hiện điều đó, điều này không liên quan đến việc tạo lớp serializer tùy chỉnh, điều này sẽ xử lý việc tuần tự hóa toàn bộ các trường của đối tượng? Hoặc có thể là nó có thể kế thừa một số "cơ bản" serializer, và chỉ cần lấy nó đầu ra và thêm lĩnh vực mới để nó bằng cách nào đó?

Tôi đã tìm hiểu về mixins và có vẻ như có thể đổi tên/ẩn một số trường, tuy nhiên có vẻ như không thể thêm một trường bổ sung.

Trả lời

8

Bạn có thể không chỉ thêm phương thức trong lớp giá trị không? Lưu ý rằng nó không phải là công khai, hoặc sử dụng quy ước đặt tên getter; bạn có thể làm một cái gì đó như:

public class MyStuff { 
    // ... the usual fields, getters and/or setters 

    @JsonProperty("sum") // or whatever name you need in JSON 
    private int calculateSumForJSON() { 
     return 42; // calculate somehow 
    } 
} 

Nếu không, bạn có thể chuyển đổi POJO thành JSON giá trị Tree:

JsonNode tree = mapper.valueToTree(value); 

và sau đó sửa đổi nó bằng cách tính thêm, vv

+0

này không hoạt động nếu các trường bổ sung không phải là một phần của đối tượng đang được seri của trách nhiệm. Ví dụ. URL của một đối tượng ... Nó không phải là công việc của đối tượng để biết địa chỉ riêng của nó, đó là một công việc của lớp cao hơn. – cdeszaq

+0

Khá, nhưng tại sao sau đó nó được tuần tự hóa trong cùng một đối tượng JSON? Điều này nghe có vẻ như thiết kế có khả năng xấu cho tải trọng JSON. Mặc dù được cấp JSON có vấn đề là không có phân chia đơn giản giữa dữ liệu, siêu dữ liệu (có thể đưa ra quy ước đặt tên) – StaxMan

+0

Biểu diễn đối tượng bên trong không giống như biểu diễn tài nguyên bên ngoài (có thể cần thay đổi tùy thuộc vào tiêu đề Chấp nhận) . URL hoặc địa chỉ mà tại đó tài nguyên cuộc sống có thể thay đổi và không phải là trách nhiệm của đối tượng bên trong mà là của các tuyến hoặc một số lớp cao hơn khác. – cdeszaq

1

Một lựa chọn là để thêm một lĩnh vực cho thuộc tính này và đặt nó trên đối tượng trước khi ghi vào JSON. Một lựa chọn thứ hai, nếu tài sản có thể được tính từ thuộc tính đối tượng khác mà bạn có thể chỉ cần thêm một getter cho nó, ví dụ:

public String getFullName() { 
    return getFirstName() + " " + getLastName(); 
} 

Và mặc dù không có trường hợp Jackson sẽ tự động gọi getter này khi viết JSON và nó sẽ xuất hiện dưới dạng fullName trong đầu ra JSON. Nếu điều đó sẽ không làm việc một lựa chọn thứ ba là để chuyển đổi các đối tượng bản đồ và sau đó vận dụng nó tuy nhiên bạn cần:

ObjectMapper mapper //..... 
MyObject o //..... 
long specialValue //..... 
Map<String, Object> map = mapper.convertValue(o, new TypeReference<Map<String, Object>>() { }); 
map.put("specialValue", specialValue); 

Bạn đang câu hỏi đã không đề cập unmarshalling nhưng nếu bạn cần phải làm điều đó cũng sau đó tùy chọn đầu tiên sẽ hoạt động tốt nhưng hai thứ hai sẽ cần một số chỉnh sửa.

Và như để viết các lĩnh vực khác nhau của cùng một đối tượng có vẻ như một công việc cho @JsonView

+0

Đối tượng "chuyển đổi thành bản đồ" có vẻ như có thể là OK, nhưng có vẻ hơi khó xử. Tùy chọn "thêm một trường" không hoạt động nếu trường bổ sung không phải là một phần của đối tượng đang được chịu trách nhiệm của hàng loạt. Ví dụ. URL của một đối tượng ... Nó không phải là công việc của đối tượng để biết địa chỉ riêng của nó, đó là một công việc của lớp cao hơn. – cdeszaq

Các vấn đề liên quan