34

Jackson を使用して、制御できない JSON を解析しています。JSON は次のようになります。

{
    "status":"0"
    "type":"type1"
    "info": {
       // additional fields
    }
}

私のクラスは次のようになります

public class Response {
    private String status;
    private String type;
    private Info info
}

使用する Info のサブクラスは type プロパティに依存するため、info のマッピングは次のとおりです。

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
@JsonSubTypes(value = {
        @JsonSubTypes.Type(value = Type1Info.class, name = "type1"),
        @JsonSubTypes.Type(value = Type2Info.class, name = "type2") })
public abstract class Info {
    // some fields
}

私が知る限り、区別する要素がキャストする必要がある要素と同じレベルにある場合、これは型情報を使用する正しい方法です。しかし、これは機能しません。常に同じエラーが発生します。

com.fasterxml.jackson.databind.JsonMappingException: 予期しないトークン (END_OBJECT)、予想される FIELD_NAME: タイプ ID を含むプロパティ 'type' がありません

EXTERNAL_PROPERTY を PROPERTY に変更しても、同じエラーが発生します。EXTERNAL_PROPERTY の私の理解は間違っていますか?

4

1 に答える 1

50

Javadoc から:

PROPERTY と同様の包含メカニズムですが、プロパティが 1 レベル上の階層に含まれる点が異なります。つまり、JSON オブジェクトと同じレベルの兄弟プロパティとして型に含まれます。この選択は、タイプ (クラス) ではなく、プロパティにのみ使用できることに注意してください。クラスに使用しようとすると、代わりに基本的な PROPERTY の包含戦略になります。

can only be used for properties太字になっていることに注意してください。ソース: JsonTypeInfo.As.EXTERNAL_PROPERTY

したがって、すべての注釈をInfoクラスからクラス内のプロパティinfoまたはsetInfoメソッドに移動する必要がありますResponse

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
@JsonSubTypes(value = { @JsonSubTypes.Type(value = Type1Info.class, name = "type1"),
        @JsonSubTypes.Type(value = Type2Info.class, name = "type2") })
public void setInfo(Info info) {
    this.info = info;
}

私にとっては、クラスtypeからプロパティも削除する必要があります。Responseシリアル化プロセス中に動的に生成されます。逆シリアル化では、ジャクソンは型を気にするので必要ありません。クラスは次のようになります。

class Response {

    private String status;
    private Info info;

    //getters, setters
}

この質問も参照してください: JSON ネスト クラス データ バインディング

于 2014-01-03T23:28:28.860 に答える