22

GSON を使用して JSON を T 型のオブジェクトにデコードしています。

public T decode(String json) {
    Gson gson = new Gson();
    return gson.fromJson(json, new TypeToken<T>() {}.getType());
}

ただし、これは例外を返します-

java.lang.AssertionError: 予期しないタイプです。次のいずれかが必要です: java.lang.reflect.ParameterizedType、java.lang.reflect.GenericArrayType、しかし得たもの: sun.reflect.generics.reflectiveObjects.TypeVariableImpl、型トークン: T

TypeToken を使用することで、Type Erasure を回避できたと思いました。

私が間違っている?

ありがとう

4

3 に答える 3

14

まず第一に、Gson をそのようにラップすることがどのように役立つかがわかりません。

Tあなたの問題に関しては、ジェネリック型自体に関する情報は実行時に利用できません。消されました。コンパイル時にのみ使用できます。のように、代わりに実際の型でパラメータ化する必要がありますnew TypeToken<List<String>>

Java には具体化された Generics がないため ( を実行することはできませんT t = new T())、Gson 自体はこのTypeTokenアプローチを使用することを余儀なくされています。そうでなければ、Gson ははるかにエレガントな方法でそれを行ったでしょう。

実際の型を渡すことができるようにするには、TypeToken既に行っているのと同じことを再発明する必要があります。そして、これは意味がありません:)それを再利用するか、そのようなヘルパークラスでラップせずにGsonをそのまま使用してください。

于 2010-11-19T16:43:00.753 に答える
5

最初の答えは実際の解決策を指摘していないと思います.Tとともにクラスインスタンスも渡す必要があります.

public T decode(String json, Class<T> cls) {
    Gson gson = new Gson();
    return gson.fromJson(json, cls);
}

これは、ここの 'T' が型参照ではなく型 VARIABLE であるためです。暗黙的なキャストを追加し、型の互換性を検証するためにコンパイラによってのみ使用されます。ただし、実際のクラスを渡すと、それを使用できます。コンパイラは型の互換性をチェックして、不一致の可能性を減らします。

または、TypeToken を取り込んで渡すこともできます。ただし、TypeToken は、型変数ではなく、実際の型で構築する必要があります。ここでは型変数はほとんど役に立ちません。ただし、何かをラップしたい場合は、呼び出し元に TypeToken (Gson 型) を使用させたくないでしょう。

同じラッピングメカニズムは、あなたが言及したジャクソンのような他のライブラリでも機能します。

于 2011-01-04T18:42:42.400 に答える