2013-10-01 21 views
5

Khi tuần tự hóa một đối tượng Java có tham chiếu đối tượng khác, tôi cần tuần tự hóa chỉ một thuộc tính của đối tượng lồng nhau (trường hợp thông thường của khóa ngoài, do đó, tuần tự hóa thuộc tính "id" của đối tượng tài liệu tham khảo). Nắm lấy mọi thứ khác.Jackson, tuần tự hóa một thuộc tính của tham chiếu

Ví dụ, tôi có hai lớp học mà tôi cần phải serialize để JSON & XML (loại bỏ chú thích JPA cho rõ ràng):

Mối quan hệ: User -> (one-to-many) AddressInformation; Ngoài ra: AddressInformation -> (one-to-one) tài

@XmlRootElement 
public class User { 
    private String id; 
    private String firstName; 
    private String lastName; 
    private String email; 
    private AddressInformation defaultAddress; 
    private Set<AddressInformation> addressInformation; 

    public User() { 
    } 

    @JsonProperty(value = "id") 
    @XmlAttribute(name = "id") 
    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    @JsonProperty(value = "firstname") 
    @XmlAttribute(name = "firstname") 
    public String getFirstName() { 
     return firstName; 
    } 

    public void setFirstName(String firstName) { 
     this.firstName = firstName; 
    } 

    @JsonProperty(value = "lastname") 
    @XmlAttribute(name = "lastname") 
    public String getLastName() { 
     return lastName; 
    } 

    public void setLastName(String lastName) { 
     this.lastName = lastName; 
    } 

    @JsonProperty(value = "email") 
    @XmlAttribute(name = "email") 
    public String getEmail() { 
     return email; 
    } 

    public void setEmail(String email) { 
     this.email = email; 
    } 

    @JsonIgnore 
    public Set<AddressInformation> getAddressInformation() { 
     return addressInformation; 
    } 

    public void setAddressInformation(Set<AddressInformation> addressInformation) { 
     this.addressInformation = addressInformation; 
    } 

    @JsonProperty(value = "defaultaddress") 
    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") 
    public AddressInformation getDefaultAddress() { 
     return defaultAddress; 
    } 

    public void setDefaultAddress(AddressInformation defaultAddress) { 
     this.defaultAddress = defaultAddress; 
    } 
} 

AddressInformation:

@XmlRootElement 
public class AddressInformation { 
    private String id; 
    private String address; 
    private String details; 
    private User user; 

    @JsonProperty(value = "id") 
    @XmlAttribute(name = "id") 
    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") 
    public User getUser() { 
     return user; 
    } 

    public void setUser(User user) { 
     this.user = user; 
    } 

    @JsonProperty(value = "details") 
    @XmlAttribute(name = "details") 
    public String getDetails() { 
     return details; 
    } 

    public void setDetails(String details) { 
     this.details = details; 
    } 

    @JsonProperty(value = "address") 
    @XmlAttribute(name = "address") 
    public String getAddress() { 
     return address; 
    } 

    public void setAddress(String address) { 
     this.address = address; 
    } 

    public AddressInformation() { 
     super(); 
    } 
} 
enter code here 

Khi serializing tài khoản ví dụ, tôi cần:

{ 
    "id" : "idofuser01", 
    "email" : "[email protected]", 
    "status" : "OK", 
    "firstname" : "Filan", 
    "lastname" : "Ovni", 
    "defaultaddressid" : "idofaddress01", 
} 
enter code here 

Khi serializing AddressInformation :

{ 
    "id" : "idofaddress01", 
    "address" : "R.8. adn", 
    "details" : "blah blah", 
    "userid" : "idofuser01", 
} 

Tôi đã thử @JsonManageReference & @JsonBackReference không thành công. Như bạn thấy, tôi cũng đã thử @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")

Trả lời

11

Chỉ cần tìm thấy một cách sử dụng Jackson 2.1+.

tham chiếu đối tượng Chú thích với (điều này sẽ chỉ chọn các thuộc tính của idAddressInformation):

@JsonProperty(value = "defaultaddressid") 
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") 
@JsonIdentityReference(alwaysAsId = true) 
public AddressInformation getDefaultAddress() { 
    return defaultAddress; 
} 

serialization hoạt động rất tốt.

+0

Công trình này, nhưng tôi không hiểu nó đang làm gì. Bạn có thể xây dựng ? – Setheron

+0

Có, bất cứ ai có thể giải thích lý do tại sao ở trên là làm việc? Cảm ơn. – HopeKing

+0

Tôi thường đặt '@ JsonIdentityInfo' ở cấp lớp và' @ JsonIdentityReference' ở cấp độ phân bổ (một tham chiếu đến lớp khác). '@ JsonIdentityInfo' tránh đệ quy vô hạn khi tuần tự hóa (như User1-> Address1-> User1-> Address1 -> ...) viết trường" id "của thực thể được tham chiếu thay vì cố gắng tuần tự hóa POJO hoàn chỉnh. NHƯNG hành vi chính là serialize sự xuất hiện đầu tiên POJO hoàn toàn, và tham khảo thêm chỉ viết 'id'. '@ JsonIdentityReference' định cấu hình lại hành vi để luôn viết id được tham chiếu, không được tuần tự hóa toàn bộ POJO; như vậy: Address1 -> "John". –

3

Bạn có thể triển khai trình gỡ rối tùy chỉnh cho lớp này và sử dụng nó trong lớp học User. thực hiện ví dụ:

class AddressInformationIdJsonSerializer extends JsonSerializer<AddressInformation> { 
    @Override 
    public void serialize(AddressInformation value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { 
     jgen.writeString(value.getId()); 
    } 
} 

Và cấu hình trong User lớp:

giải pháp
@JsonProperty(value = "defaultaddress") 
@JsonSerialize(using = AddressInformationIdJsonSerializer.class) 
public AddressInformation getDefaultAddress() { 
    return defaultAddress; 
} 

### Generic cho mọi tầng lớp mà thực hiện một giao diện ###
Bạn có thể tạo giao diện, trong đó có phương pháp String getId() :

interface Identifiable { 
    String getId(); 
} 

Trình nối tiếp cho giao diện này có thể trông giống như sau:

class IdentifiableJsonSerializer extends JsonSerializer<Identifiable> { 
    @Override 
    public void serialize(Identifiable value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { 
     jgen.writeString(value.getId()); 
    } 
} 

Và bây giờ, bạn có thể sử dụng bộ nối tiếp này cho tất cả các triển khai Identifiable. Ví dụ:

@JsonProperty(value = "defaultaddress") 
@JsonSerialize(using = IdentifiableJsonSerializer.class) 
public AddressInformation getDefaultAddress() { 
    return defaultAddress; 
} 

tất nhiên: AddressInformation phải thực hiện giao diện này:

class AddressInformation implements Identifiable { 
    .... 
} 
+0

Cảm ơn. Có thể viết serializer chung như vậy (không sử dụng sự phản chiếu) để sử dụng bất cứ nơi nào tôi cần chức năng? – isah

+0

Bạn muốn sử dụng bộ nối tiếp này cho tất cả các lớp POJO có thuộc tính "id chuỗi riêng", có? Bạn có thể xác nhận? –

+0

Tôi đã giải quyết được vấn đề nhưng có, Sẽ rất thú vị nếu có một bộ nối tiếp chung cho tất cả các POJO. – isah

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