ネストされたジェネリッククラスをGSONで逆シリアル化するときの奇妙な動作

は:

サーバーに接続し、いくつかの引数に基づいて、GSONで(ジェネリックを介して)指定されたクラスに解析されるjson-stringを取得するクラスを作成しています。

担当クラスのストリップバージョンは次のようになります。

class Executor<T> {

    private Response<T> response;

    public void execute() {
        Type responseType = new TypeToken<Response<T>>() {}.getType();
        this.response = new Gson().fromJson(json, responseType);
    }

    public Response<T> getResponse() { return this.response; }

}

(- JSON変数は次のようになります。)

逆シリアル化されたデータを格納するクラスは次のようになります。

class Response<T> {

    private List<T> data = null;

    public List<T> getData() { return this.data; }

}

データが逆シリアル化されるクラス:

public class Language {
    public String alias;
    public String label;
}

そして実行するコードは上記のクラスを利用します:

Executor<Language> executor = new Executor<Language();
List<Language> languages = executor.execute().getResponse().getData();
System.out.println(languages.get(0).alias); // exception occurs here

次の例外が発生します

ClassCastException:com.google.gson.internal.StringMapをsunnerberg.skolbibliotek.book.Languageにキャストできません

ヘルプや提案は大歓迎です!

マット:

簡単に言えば、TypeTokenoutの作成を移動し、トークン(を作成するときExecutorTinをバインドして、型トークンをコンストラクターに渡す必要があるということですResponse<T>new TypeToken<Response<Language>>() {}Executor

長い答えは:

タイプのジェネリックは、ジェネリックパラメーターがバインドされてコンパイルされた場合を除き、通常は実行時に消去されますその場合、コンパイラーは総称型情報をコンパイル済みクラスに挿入します。それ以外の場合、それは不可能です。

たとえば、次のことを考慮してください。

List<Integer> foo = new ArrayList<Integer>();

class IntegerList extends ArrayList<Integer> { ... }
List<Integer> bar = new IntegerList();

実行時に型がコンパイル時にバインドされるため、Javaには整数 bar含まれていることわかり、ジェネリック型情報はクラスファイルに保存されます。ただし、のジェネリック型情報は消去されるため、実行時にが含まれいると判断すること実際には不可能です。IntegerArrayListIntegerListfoofooInteger

そのため、GSONでJSONデータを解析する場合のように、実行前に通常は消去される状況で、ジェネリック型情報が必要になることがよくあります。これらの状況では型トークンIntegerListを使用することにより、コンパイル時に型情報が(上記例のように)バインドされたときに保持されるという事実を利用できます。

今あなたのコードに:

Type responseType = new TypeToken<Response<T>>() {}.getType();

Executorクラスのこの行で、コンパイル時にハードコードされた(バインドされた)TypeTokenタイプの匿名クラス(から継承Response<T>)を作成します。したがって、実行時に、GSONはのオブジェクトが必要かどうかを判断できますResponse<T>しかしT、コンパイル時にそれを指定しなかったので、それは何であるかわかりませんそのため、GSON は、作成ListするResponseオブジェクトのどのタイプになるかを判断できずStringMap代わりにを作成します。

この話の教訓は、Tコンパイル時にそれを指定する必要があるということですExecutor総称的に使用することを意図している場合は、おそらくクライアントコードで、そのクラスの外部にタイプトークンを作成する必要があります。何かのようなもの:

class Executor<T> {

    private TypeToken<Response<T>> responseType;
    private Response<T> response;

    public Executor(TypeToken<Response<T>> responseType) {
        this.responseType = responseType;
    }

    public void execute() {
        this.response = new Gson().fromJson(json, responseType.getType());
    }

    public Response<T> getResponse() { return this.response; }

}

// client code:
Executor<Language> executor = new Executor<Language>(new TypeToken<Response<Language>>() { });
executor.execute();
List<Language> languages = executor.getResponse().getData();
System.out.println(languages.get(0).alias); // prints "be"

ちなみに、私は私のマシンで上記をテストしました。

長すぎると申し訳ありません!

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

ネストされたオブジェクトをGSONで逆シリアル化します

分類Dev

KotlinでGsonを使用してネストされたクラスを逆シリアル化する方法は?

分類Dev

GSONで逆シリアル化されている親オブジェクトのパラメーターを使用して子オブジェクトをインスタンス化し、ジェネリックを使用しますか?

分類Dev

InstanceCreatorでネストされたオブジェクトをGSON逆シリアル化

分類Dev

コレクションを逆シリアル化するときの安全でないジェネリックキャスト

分類Dev

Javaクラスと同じ名前のネストされたJSONオブジェクトを逆シリアル化する方法

分類Dev

Gsonシリアル化:ジェネリッククラスとジェネリックデータをその中にキャストする方法は?

分類Dev

JSONから複雑なネストされたJavaオブジェクトを逆シリアル化する

分類Dev

.NETJSONを逆シリアル化するときにネストされたオブジェクトを解析できません

分類Dev

JSONでラップされたコレクションプロパティをジェネリッククラスに逆シリアル化する方法は?

分類Dev

ネストされたオブジェクトをシリアル化するときの自己参照

分類Dev

GSONでジェネリッククラスをシリアル化する際のstackoverflowエラー

分類Dev

フラット構造でネストされたオブジェクトをシリアル化/逆シリアル化

分類Dev

オブジェクトのラップされたリストのGSON逆シリアル化

分類Dev

C#でのNewtonsoftによるネストされたJSONオブジェクトの逆シリアル化

分類Dev

ネストされたオブジェクトのJavaJackson逆シリアル化

分類Dev

ジェネリック型のgsonでカスタム逆シリアル化を使用するにはどうすればよいですか?

分類Dev

Django RestFrameworkを使用してネストされたオブジェクトを逆シリアル化する方法

分類Dev

JSONオブジェクトを逆シリアル化して、特定のフィールドをネストされたオブジェクトではなく文字列として保持するにはどうすればよいですか?

分類Dev

バッチスクリプトでのネストされたラベルの奇妙な動作

分類Dev

クラス内のネストされたメソッドで「タスクをシリアル化できない」を回避する

分類Dev

フラットオブジェクトをネストされたJSON構造にシリアル化する

分類Dev

Newton.Jsonの逆シリアル化されたジェネリックオブジェクトをカスタムオブジェクトにキャストするにはどうすればよいですか?

分類Dev

Javaのジャクソンライブラリを使用してネストされたJSON配列をマップに逆シリアル化する方法は?

分類Dev

jsonをジェネリック型のベースオブジェクトに逆シリアル化する

分類Dev

GSONを使用したジェネリック型の逆シリアル化

分類Dev

Gsonを使用したジェネリック型のJava逆シリアル化

分類Dev

Jackson Databindを使用してネストされたジェネリッククラスを逆シリアル化するにはどうすればよいですか?

分類Dev

複雑な(ネストされた)JSONのC#オブジェクトへの逆シリアル化

Related 関連記事

  1. 1

    ネストされたオブジェクトをGSONで逆シリアル化します

  2. 2

    KotlinでGsonを使用してネストされたクラスを逆シリアル化する方法は?

  3. 3

    GSONで逆シリアル化されている親オブジェクトのパラメーターを使用して子オブジェクトをインスタンス化し、ジェネリックを使用しますか?

  4. 4

    InstanceCreatorでネストされたオブジェクトをGSON逆シリアル化

  5. 5

    コレクションを逆シリアル化するときの安全でないジェネリックキャスト

  6. 6

    Javaクラスと同じ名前のネストされたJSONオブジェクトを逆シリアル化する方法

  7. 7

    Gsonシリアル化:ジェネリッククラスとジェネリックデータをその中にキャストする方法は?

  8. 8

    JSONから複雑なネストされたJavaオブジェクトを逆シリアル化する

  9. 9

    .NETJSONを逆シリアル化するときにネストされたオブジェクトを解析できません

  10. 10

    JSONでラップされたコレクションプロパティをジェネリッククラスに逆シリアル化する方法は?

  11. 11

    ネストされたオブジェクトをシリアル化するときの自己参照

  12. 12

    GSONでジェネリッククラスをシリアル化する際のstackoverflowエラー

  13. 13

    フラット構造でネストされたオブジェクトをシリアル化/逆シリアル化

  14. 14

    オブジェクトのラップされたリストのGSON逆シリアル化

  15. 15

    C#でのNewtonsoftによるネストされたJSONオブジェクトの逆シリアル化

  16. 16

    ネストされたオブジェクトのJavaJackson逆シリアル化

  17. 17

    ジェネリック型のgsonでカスタム逆シリアル化を使用するにはどうすればよいですか?

  18. 18

    Django RestFrameworkを使用してネストされたオブジェクトを逆シリアル化する方法

  19. 19

    JSONオブジェクトを逆シリアル化して、特定のフィールドをネストされたオブジェクトではなく文字列として保持するにはどうすればよいですか?

  20. 20

    バッチスクリプトでのネストされたラベルの奇妙な動作

  21. 21

    クラス内のネストされたメソッドで「タスクをシリアル化できない」を回避する

  22. 22

    フラットオブジェクトをネストされたJSON構造にシリアル化する

  23. 23

    Newton.Jsonの逆シリアル化されたジェネリックオブジェクトをカスタムオブジェクトにキャストするにはどうすればよいですか?

  24. 24

    Javaのジャクソンライブラリを使用してネストされたJSON配列をマップに逆シリアル化する方法は?

  25. 25

    jsonをジェネリック型のベースオブジェクトに逆シリアル化する

  26. 26

    GSONを使用したジェネリック型の逆シリアル化

  27. 27

    Gsonを使用したジェネリック型のJava逆シリアル化

  28. 28

    Jackson Databindを使用してネストされたジェネリッククラスを逆シリアル化するにはどうすればよいですか?

  29. 29

    複雑な(ネストされた)JSONのC#オブジェクトへの逆シリアル化

ホットタグ

アーカイブ