web-dev-qa-db-ja.com

ジャクソン-ジェネリッククラス変数の逆シリアル化

質問を間違って投稿しました。ここに質問を正しく投稿しています...

HTTP応答としてjson文字列を取得しています。私はそれの構造を知っています。以下のとおりです。

public class Json<T> {
    public Hits<T> hits;
}
public class Hits<T> {
    public int found;
    public int start;
    public ArrayList<Hit<T>> hit;
}
public class Hit<T> {
    public String id;
    public Class<T> data;
}

「データ」フィールドは、任意のクラスに属することができます。実行時にのみそれを知っています。パラメータとして取得します。これは、私が逆シリアル化する方法です。

public <T> void deSerialize(Class<T> clazz) {
    ObjectMapper mapper = new ObjectMapper();
    mapper.readValue(jsonString,  new TypeReference<Json<T>>() {});
}

しかし、エラーが発生します-

java.lang.classからプライベートJava.lang.class.Class()にアクセスできません。アクセスの設定に失敗しました。 Java.lang.Classコンストラクタをアクセス可能にすることはできません

24
gnjago

ジェネリック型が動的にしか利用できない場合は、明示的にJavaTypeをビルドする必要があります。

// do NOT create new ObjectMapper per each request!
final ObjectMapper mapper = new ObjectMapper();

public Json<T> void deSerialize(Class<T> clazz, InputStream json) {
    return mapper.readValue(json,
      mapper.getTypeFactory().constructParametricType(Json.class, clazz));
}
26
StaxMan

サンプルの一般的な逆シリアル化インターフェイス:

public interface Deserializable<T> {
    static final ObjectMapper mapper = new ObjectMapper();

    @SuppressWarnings("unchecked")
    default T deserialize(String rawJson) throws IOException {
        return mapper.readValue(rawJson, (Class<T>) this.getClass());
    }
}
5
Jose Alban

ClassオブジェクトをJSONにシリアル化および逆シリアル化していますか?多分それをヒットの文字列として保持し、Class.forNameを起動する追加のゲッターを作成します。

public class Hit {
    public String id;
    public String data;
    public Class<?> getDataClass() throws Exception {
       return Class.forName(data);
    }
}
1
Piotr Gwiazda

逆シリアル化が必要なJSON文字列には、パラメーターTに関する型情報を含める必要があります。
パラメータTの型情報ができるように、パラメータJsonとしてクラスTに渡すことができるすべてのクラスにジャクソンアノテーションを付ける必要があります。ジャクソンによってJSON文字列から読み書きされます。

Tは、抽象クラスResultを拡張する任意のクラスであると想定します。

public class Json<T extends Result> {
    public Hits<T> hits;
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({
        @JsonSubTypes.Type(value = ImageResult.class, name = "ImageResult"),
        @JsonSubTypes.Type(value = NewsResult.class, name = "NewsResult")})
public abstract class Result {

}

public class ImageResult extends Result {

}

public class NewsResult extends Result {

}

パラメーターTとして渡すことができる各クラス(またはそれらの共通のスーパータイプ)に注釈が付けられると、JacksonはパラメーターTに関する情報をJSONに含めます。このようなJSONは、コンパイル時にパラメーターTを知らなくても逆シリアル化できます。
これ Jacksonドキュメントリンク は多態性逆シリアル化について説明しますが、この質問についても参照するのに役立ちます。

0
Sanjeev Sachdev