次のクラスにデシリアライズする必要があるjson文字列があります
class Data <T> {
int found;
Class<T> hits
}
どうすればいいのですか?これが通常の方法です
mapper.readValue(jsonString, Data.class);
しかし、T の略をどのように説明すればよいでしょうか。
TypeReference
使用するジェネリック型ごとにオブジェクトを作成し、それを逆シリアル化に使用する必要があります。例えば -
mapper.readValue(jsonString, new TypeReference<Data<String>>() {});
それはできません: のように、完全に解決された型を指定する必要がありますData<MyType>
。T
は単なる変数であり、無意味です。
しかし、それT
が既知であることを意味する場合は、静的ではなく、TypeReference
動的に相当するものを作成する必要があります。参照されている他の質問ですでにこれについて言及されている場合がありますが、次のようになります。
public Data<T> read(InputStream json, Class<T> contentClass) {
JavaType type = mapper.getTypeFactory().constructParametricType(Data.class, contentClass);
return mapper.readValue(json, type);
}
最初に行うことはシリアライズであり、次にデシリアライズを行うことができます。
したがって、シリアル化するときは@JsonTypeInfo
、jackson がクラス情報を json データに書き込めるようにするために使用する必要があります。あなたができることは次のようなものです:
Class Data <T> {
int found;
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
Class<T> hits
}
次に、逆シリアル化すると、jackson がデータを、変数が実際に実行時にヒットするクラスに逆シリアル化したことがわかります。
クラス Data<> の場合
ObjectMapper mapper = new ObjectMapper();
JavaType type = mapper.getTypeFactory().constructParametrizedType(Data.class, Data.class, Parameter.class);
Data<Parameter> dataParam = mapper.readValue(jsonString,type)
ジェネリック型の型を知っている別のクラスでラップすることができます。
例えば、
class Wrapper {
private Data<Something> data;
}
mapper.readValue(jsonString, Wrapper.class);
ここで何かが具体的なタイプです。具体化されたタイプごとにラッパーが必要です。そうでなければ、ジャクソンはどのオブジェクトを作成するかを知りません。