GSONで、実行するオブジェクトのリストを取得します
Gson gson = new Gson();
Type token = new TypeToken<List<MyType>>(){}.getType();
return gson.fromJson(json, token);
それはうまく機能しますが、このコードでオブジェクトのリストを解析する一般的な機能を持つことができるように、さらに進んでMyTypeをパラメータ化したいです
// the common function
public <T> List<T> fromJSonList(String json, Class<T> type) {
Gson gson = new Gson();
Type collectionType = new TypeToken<List<T>>(){}.getType();
return gson.fromJson(json, collectionType);
}
// the call
List<MyType> myTypes = parser.fromJSonList(jsonString, MyType.class);
悲しいことに、型ではなくStringMapsの配列を返します。 Tは、私の型ではなく、別のジェネリック型として解釈されています。回避策はありますか?
ジェネリックはコンパイル時に機能します。スーパータイプトークンが機能する理由は、(匿名の)内部クラスがバイト引数メタデータに直接格納されているジェネリックスーパークラス(スーパーインターフェイス)の型引数にアクセスできるためです。
.Javaソースファイルがコンパイルされると、タイプパラメータ_<T>
_は明らかに破棄されます。コンパイル時には不明であるため、バイトコードに格納できないため、消去され、Gsonは読み取ることができません。
[〜#〜] update [〜#〜]
Newacctの答えの後、私は彼がオプション2で提案したもの、つまりParameterizedType
を実装しようとしました。コードは次のようになります(基本的な test ):
_class ListOfSomething<X> implements ParameterizedType {
private Class<?> wrapped;
public ListOfSomething(Class<X> wrapped) {
this.wrapped = wrapped;
}
public Type[] getActualTypeArguments() {
return new Type[] {wrapped};
}
public Type getRawType() {
return List.class;
}
public Type getOwnerType() {
return null;
}
}
_
このコードの目的は、getFromJsonList()
内で使用することです。
_public List<T> fromJsonList(String json, Class<T> klass) {
Gson gson = new Gson();
return gson.fromJson(json, new ListOfSomething<T>(klass));
}
_
テクニックが機能し、実際に非常に巧妙であっても(私はそれを知りませんでしたし、考えもしなかったでしょう)、これが最終的な成果です。
_List<Integer> list = new Factory<Integer>()
.getFromJsonList(text, Integer.class)
_
の代わりに
_List<Integer> list = new Gson().fromJson(text,
new TypeToken<List<Integer>>(){}.getType());
_
私にとっては、TypeToken
sがコードを厄介に見せることに同意しても、これらすべては役に立たないことになります:P
_gson 2.8.0
_なので、 TypeToken#getParametized((Type rawType, Type... typeArguments))
を使用してtypeToken
を作成できます。その後、getType()
がトリックを実行します。
例えば:
_TypeToken.getParameterized(List.class, myType).getType();
_
public static final <T> List<T> getList(final Class<T[]> clazz, final String json)
{
final T[] jsonToObject = new Gson().fromJson(json, clazz);
return Arrays.asList(jsonToObject);
}
例:
getList(MyClass[].class, "[{...}]");
Raffaele's をさらに一歩進めてクラスを生成し、すべてのクラスA(Bはパラメーター化されていないクラス)で機能するようにしました。セットやその他のコレクションに役立つ場合があります。
public class GenericOf<X, Y> implements ParameterizedType {
private final Class<X> container;
private final Class<Y> wrapped;
public GenericOf(Class<X> container, Class<Y> wrapped) {
this.container = container;
this.wrapped = wrapped;
}
public Type[] getActualTypeArguments() {
return new Type[]{wrapped};
}
public Type getRawType() {
return container;
}
public Type getOwnerType() {
return null;
}
}
@oldergodからの素晴らしい答えに基づいた完全なコードベースを次に示します。
public <T> List<T> fromJSonList(String json, Class<T> myType) {
Gson gson = new Gson();
Type collectionType = TypeToken.getParameterized(List.class, myType).getType();
return gson.fromJson(json, collectionType);
}
を使用して
List<MyType> myTypes = parser.fromJSonList(jsonString, MyType.class);
お役に立てば幸いです
これは以前の質問で回答されています。基本的に、2つのオプションがあります。
Type
を渡します。呼び出しコードはTypeToken
またはそれを構築するために何でも使用します。Type
を自分で作成します。これには、ParameterizedType
を実装するクラスを記述する必要がありますKotlinでプログラミングする場合は、reified type parameter
インライン関数
class GenericGson {
companion object {
inline fun <reified T : Any> Gson.fromJsonTokenType(jsonString: String): T {
val type = object : TypeToken<T>() {}.type
return this.fromJson(jsonString, type)
}
inline fun <reified T : Any> Gson.fromJsonType(jsonString: String): T = this.fromJson(jsonString, T::class.Java)
inline fun <reified T : Any> fromJsonTokenType(jsonString: String): T = Gson().fromJsonTokenType(jsonString)
inline fun <reified T : Any> fromJsonType(jsonString: String): T = Gson().fromJsonType(jsonString)
}
}
そして、あなたのコードで以下のように使用してください
val arrayList = GenericGson.fromJsonTokenType<ArrayList<Person>>(json)
Kotlinの簡単な使用例:
プレースの取得機能
fun getPlaces<T> (jsonString : String, clazz: Class<T>) : T { val places : T = Gson().fromJson(jsonString,clazz) return places }
その後、次のように使用できます
val places = getPlaces(Array<Place>::class.Java)
public static <T> T getObject(String gsonStr) {
Gson gson = new GsonBuilder()
.setLenient()
.create();
Type collectionType = new TypeToken< T>(){}.getType();
return gson.fromJson(gsonStr,
collectionType);
}
使用する場合:
Class1 class1= getObject(jsonStr);
私のために働いたコトリン「ListOfSomething」ソリューション:
fun <T: Any> getGsonList(json: String, kclass: KClass<T>) : List<T> {
return getGsonInstance().fromJson<List<T>>(json, ListOfSomething<T>(kclass.Java))
}
internal class ListOfSomething<X>(wrapped: Class<X>) : ParameterizedType {
private val wrapped: Class<*>
init {
this.wrapped = wrapped
}
override fun getActualTypeArguments(): Array<Type> {
return arrayOf<Type>(wrapped)
}
override fun getRawType(): Type {
return ArrayList::class.Java
}
override fun getOwnerType(): Type? {
return null
}
}