2013-08-14 22 views
12

私はSpringと併用してJSON(de)直列化にJacksonを使用しています。しかし、場合によっては2倍のフィールドに問題があります。JacksonとJSONフィールドが重複しています。

私は抽象クラスがあります。

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

そして、具象クラス、抽象を拡張する:

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フィールドを取得することです:

{ 
    "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を削除する場合は、含ま'AbstractBookmarkJsonModel'から' mimeType'をjsonに1つだけ持ちます – 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)をプロとして名前mimeTypeproperty = "mimeType")のperty(JsonTypeInfo.As.PROPERTY)です。 @JsonSubTypes.Typeで論理名application/epub+zipEpubBookmarkJsonModelに割り当てます。それは直列化になると

は、ジャクソンが財産mimeType = "application/epub+zip"として論理名をシリアル化し、それらの間でオブジェクトのプロパティ (コンストラクタに割り当てられた)論理名application/epub+zipと同じ値を持つことが起こるmimeType

私はジャクソンが型情報のシリアライズを通じてそのの世話をしますので、mimeTypemimeTypeフィールドを削除する@JsonTypeInfo注釈またはより良いにobjectTypeに変更されるべきだと思います。

+1

+1これは正解ですが、Jacksonはシリアル化されたJSON出力に追加のプロパティを追加していますサブタイプを特定する。あなたのケースでは、既存のプロパティを使用しようとすると、そうしてはいけません。私はあなたがそれを必要と思うので、あなたはクラスから 'mimeType'プロパティを削除できないことを知っています。 'subtypeName'のような別のサブタイプ情報プロパティー名を使うだけで、サブタイプ名は' 'ImageBookmark'"と "' 'EpubBookmark'"のようなものを使います。これはJacksons Polymorphic Type Handlingの意図した使い方です。 –

6

私はこの重複した出力に関して全く同じ問題を抱えていました。私は別のプロパティを含まないソリューションを見つけ、元のプロパティを削除しないようにしました。まず、JsonTypeInfoのvisibleフラグをtrueに設定します。次に、JsonIgnoreアノテーションをプロパティ宣言とゲッターに追加しました(ただしsetterはありません)。これまでは、typeプロパティのキーが1つのみで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

関連する問題