복붙노트

[SPRING] Jackson, 참조의 한 속성을 직렬화

SPRING

Jackson, 참조의 한 속성을 직렬화

다른 객체 참조가있는 Java 객체를 직렬화 할 때 중첩 객체의 하나의 속성 (일반적으로 외래 키의 경우이므로 객체 참조의 "id"속성을 직렬화) 만 직렬화해야합니다. 다른 모든 것들을 넣으십시오.

예를 들어 JSON과 XML로 직렬화해야하는 두 개의 클래스가 있습니다 (명확성을 위해 JPA 주석을 제거했습니다).

관계 : 사용자 -> (일대 다) AddressInformation; 또한 : AddressInformation -> (일대일) 사용자

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

주소 정보 :

@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

예를 들어 사용자를 serialize 할 때 필요한 것은 다음과 같습니다.

{
  "id" : "idofuser01",
  "email" : "some.email@gmail.com",
  "status" : "OK",
  "firstname" : "Filan",
  "lastname" : "Ovni",
  "defaultaddressid" : "idofaddress01",
}
enter code here

AddressInformation을 직렬화 할 때 :

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

나는 아무 성공없이 @JsonManageReference & @JsonBackReference를 시도했다. 보시다시피 저는 @JsonIdentityInfo (generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")를 시도했습니다.

해결법

  1. ==============================

    1.방금 Jackson 2.1+를 사용하여 발견했습니다.

    방금 Jackson 2.1+를 사용하여 발견했습니다.

    개체 참조에 주석 달기 (AddressInformation의 id 특성 만 선택합니다) :

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

    직렬화가 잘 작동합니다.

  2. ==============================

    2.이 클래스에 대한 사용자 정의 직 병렬 변환기를 구현하고이를 User 클래스에서 사용할 수 있습니다. 구현 예 :

    이 클래스에 대한 사용자 정의 직 병렬 변환기를 구현하고이를 User 클래스에서 사용할 수 있습니다. 구현 예 :

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

    그리고 사용자 클래스의 구성 :

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

    ### 하나의 인터페이스를 구현하는 모든 클래스에 대한 일반적인 해결책 ### String getId () 메서드가 포함 된 인터페이스를 만들 수 있습니다.

    interface Identifiable {
        String getId();
    }
    

    이 인터페이스의 serializer는 다음과 같습니다.

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

    이제는 모든 식별 가능한 구현에 대해이 serializer를 사용할 수 있습니다. 예 :

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

    물론 : AddressInformation이 인터페이스를 구현해야합니다 :

    class AddressInformation implements Identifiable {
        ....
    }
    
  3. from https://stackoverflow.com/questions/19118059/jackson-serialize-one-attribute-of-a-reference by cc-by-sa and MIT license