私は、制御できない JSON を解析するために Jackson を使用しています。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 の理解が間違っているのでしょうか?
ベストアンサー1
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
。これは、シリアル化プロセス中に動的に生成されます。デシリアライズでは、Jackson が型を気にするため、プロパティは必要ありません。クラスは次のようになります。
class Response {
private String status;
private Info info;
//getters, setters
}
この質問も参照してください:JSON ネスト クラス データ バインディング。