2013-08-14 3 views
12

저는 Spring과 함께 JSON (de) 직렬화에 Jackson을 사용하고 있습니다. 그러나 어떤 경우에는 필드가 두 번 나타나는 문제가 있습니다.Jackson과 중복 된 JSON 필드

public class EpubBookmarkJsonModel extends AbstractBookmarkJsonModel { 
    private static final long serialVersionUID = 1L; 
    // Removed other fields for brevity 

    public EpubBookmarkJsonModel() { 
     this.mimeType = "application/epub+zip"; 
    } 
} 

문제는 내가이 JSON를 직렬화 할 때, 나는 중복 mimeType 필드를 얻을 수 있다는 것입니다 :

추상을 확장

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "mimeType") 
@JsonSubTypes({ 
    @JsonSubTypes.Type(value = ImageBookmarkJsonModel.class, name = "image/jpeg"), 
    @JsonSubTypes.Type(value = EpubBookmarkJsonModel.class, name = "application/epub+zip") 
}) 
public abstract class AbstractBookmarkJsonModel extends AbstractJsonModel { 
    protected String mimeType; 
    // Removed other fields for brevity 

    public String getMimeType() { 
     return mimeType; 
    } 

    public void setMimeType(String mimeType) { 
     this.mimeType = mimeType; 
    } 

    @Override 
    public String toString() { 
     ObjectMapper mapper = new ObjectMapper(); 

     try { 
      return mapper.writeValueAsString(this); 
     } catch (IOException e) { 
      throw new IllegalStateException("Cannot convert object of type " + this.getClass().toString() + " to JSON", e); 
     } 
    } 
} 

그리고 구체적인 클래스 :

나는 추상 클래스가
{ 
    "mimeType": "application/epub+zip", 
    "mimeType": "application/epub+zip", 
    "userId": 24, 
    "acid": "ACID-000000000029087", 
    "added": "2013-08-14T12:02:17Z", 
    "epubBookmarkId": 34, 
    "cfi": "epubcfi(/6/4!/2/68)", 
    "context": "CONTEXT" 
} 

나는 previousanswers@JsonAutoDetect 주석을 사용하여 클래스의 필드 만 사용하고 ObjectMapper에 같은 필드를 설정하도록 지정해야하지만 문제가 해결되지 않습니다.

주석 :

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, 
     setterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.NONE, 
     isGetterVisibility = JsonAutoDetect.Visibility.NONE) 

ObjectMapper :

ObjectMapper mapper = new ObjectMapper(); 
    mapper.getSerializationConfig().getDefaultVisibilityChecker() 
      .withFieldVisibility(JsonAutoDetect.Visibility.ANY) 
      .withGetterVisibility(JsonAutoDetect.Visibility.NONE) 
      .withSetterVisibility(JsonAutoDetect.Visibility.NONE) 
      .withCreatorVisibility(JsonAutoDetect.Visibility.NONE); 
+0

,하지만 당신은 주석'@JsonTypeInfo (사용 = JsonTypeInfo.Id.NAME를 제거하는 경우, =이 포함

프로젝트입니다 오픈 소스, 여기를 체크 아웃 JSONTypeInfo.As.PROPERTY, property = "mimeType") 'AbstractBookmarkJsonModel' 그러면 json에 하나의'mimeType' 만있을 것입니다. – Katona

답변

5

이 동작은 클래스 AbstractBookmarkJsonModel에 배치 된 주석에 의해 발생 :

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "mimeType") 
@JsonSubTypes({ 
    @JsonSubTypes.Type(value = ImageBookmarkJsonModel.class, name = "image/jpeg"), 
    @JsonSubTypes.Type(value = EpubBookmarkJsonModel.class, name = "application/epub+zip") 
}) 

@JsonTypeInfo 논리 유형 이름을 직렬화 잭슨을 알려줍니다 (JsonTypeInfo.Id.NAME)을 프로로 (JsonTypeInfo.As.PROPERTY)이며 이름이 mimeType (property = "mimeType")입니다. @JsonSubTypes.Type을 사용하면 논리 이름 application/epub+zipEpubBookmarkJsonModel에 할당합니다. 이 직렬화에 관해서

는 잭슨이 속성 mimeType = "application/epub+zip"으로 논리적 이름을 직렬화 후, 그 (것)들의 사이에서 개체의 속성 (생성자에서 할당) 논리적 이름 application/epub+zip와 같은 값을 가지고 발생 mimeType.

나는 잭슨이 유형의 정보를 직렬화를 통해이 알아서하기 때문에 mimeTypemimeType 필드를 제거하기 위해 @JsonTypeInfo 주석에 objectType 변경 또는 더 나은해야한다고 생각합니다.

+1

+1 이것이 올바른 대답인데, Jackson은 직렬화 된 JSON 출력에 추가 속성을 추가합니다. 하위 유형을 식별하십시오. 기존 속성을 사용하려고하면 그렇게해서는 안됩니다. 나는 당신이 그것을 필요로한다고 생각하기 때문에 클래스로부터'mimeType' 속성을 제거 할 수 없다는 것을 알고있다. 'subtypeName'과 같은 다른 subtype 정보 속성 이름을 사용하고 하위 유형 이름은 "ImageBookmark'"및 "EpubBookmark'"와 같은 것을 사용하기 만하면됩니다. 이것은 Jacksons Polymorphic Type Handling의 의도 된 사용법입니다. –

6

중복 출력과 똑같은 문제가 발생했습니다. 다른 속성을 포함하지 않은 솔루션을 발견하고 원래 속성을 제거하지 못하게했습니다. 먼저 JsonTypeInfo에 대해 visible 플래그를 true로 설정합니다. 그런 다음 JsonIgnore 주석을 속성 선언과 getter에 추가했습니다 (그러나 setter는 제외). 이것은 지금까지 type 속성에 대해 하나의 키만 사용하여 JSON을 올바르게 출력합니다.

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, visible = true, property = "mimeType") 
@JsonSubTypes({ 
    @JsonSubTypes.Type(value = ImageBookmarkJsonModel.class, name = "image/jpeg"), 
    @JsonSubTypes.Type(value = EpubBookmarkJsonModel.class, name = "application/epub+zip") 
}) 
public abstract class AbstractBookmarkJsonModel extends AbstractJsonModel { 
    @JsonIgnore 
    @JsonProperty("mimeType") 
    protected String mimeType; 

    @JsonIgnore 
    @JsonProperty("mimeType") 
    public String getMimeType() { 
     return mimeType; 
    } 

    @JsonProperty("mimeType") 
    public void setMimeType(String mimeType) { 
     this.mimeType = mimeType; 
    } 

} 

주의 방법이 내가 @JsonTypeInfo 주석의 JsonTypeInfo.As.EXISTING_PROPERTY를 사용하여이 문제를 해결 fasterxml 잭슨 잭슨 - 데이터 바인딩 2.1.1

<dependency> 
    <groupId>com.fasterxml.jackson.core</groupId> 
    <artifactId>jackson-databind</artifactId> 
    <version>2.1.1</version> 
</dependency> 
15

함께.그것이 도움이 아닌지 모르겠어요 ANS.java

+1

@JsonTypeInfo에서 visible = true 인 좋은 해결책 (그렇지 않은 경우 직렬화 후 속성이 null 임) –

+0

제 생각에는 허용 된 대답이어야합니다. 그것은 잭슨의 가장 깨끗한 사용법입니다. –

+0

"toJson()"에서 작동했지만 "fromJson()"을 시도하면 필드가 "null"값으로 남았습니다. 이견있는 사람? – ozma

관련 문제