私のAndroidアプリケーション(Gsonライブラリを使用)でのJson Deserializationの実装に問題があります
私はこのようなクラスを作りました
public class MyJson<T>{
public List<T> posts;
}
そして、逆シリアル化の呼び出しは次のとおりです。
public class JsonDownloader<T> extends AsyncTask<Void, Void, MyJson<T>> {
...
protected MyJson<T> doInBackground(Void... params) {
...
Reader reader = new InputStreamReader(content);
GsonBuilder gson = new GsonBuilder();
Type collectionType = new TypeToken<MyJson<T>>() {}.getType();
result = gson.create().fromJson(reader, collectionType);
...
}
}
問題は、呼び出し後のresult.postsリストが、MyJsonオブジェクトの代わりにLinkedTreeMapオブジェクトの配列を1つ保持していることです(正しい値であるため、問題は逆シリアル化です)。 Tの代わりにMyObjectを使用すると、すべてが正常に実行され、MyObjectが正しくなります。
カスタムデシリアライザーを作成せずにデシリアライズ呼び出しを実装する方法はありますか?
直列化復元時にT
のタイプを指定する必要があります。 List
がインスタンス化するposts
を知らなかった場合、Gson
のType
はどのように作成されますか? T
を永久に維持することはできません。したがって、T
型をClass
パラメーターとして提供します。
ここで、posts
のタイプはString
であると仮定すると、MyJson<String>
をデシリアライズします(簡単にするためにString json
パラメーターも追加しました。reader
従来通り):
doInBackground(String.class, "{posts: [\"article 1\", \"article 2\"]}");
protected MyJson<T> doInBackground(Class<T> type, String json, Void... params) {
GsonBuilder gson = new GsonBuilder();
Type collectionType = new TypeToken<MyJson<T>>(){}.getType();
MyJson<T> myJson = gson.create().fromJson(json, collectionType);
System.out.println(myJson.getPosts()); // ["article 1", "article 2"]
return myJson;
}
同様に、MyJson
of Boolean
オブジェクトをデシリアライズするには
doInBackground(Boolean.class, "{posts: [true, false]}");
protected MyJson<T> doInBackground(Class<T> type, String json, Void... params) {
GsonBuilder gson = new GsonBuilder();
Type collectionType = new TypeToken<MyJson<T>>(){}.getType();
MyJson<T> myJson = gson.create().fromJson(json, collectionType);
System.out.println(myJson.getPosts()); // [true, false]
return myJson;
}
私の例ではMyJson<T>
を次のように仮定しています
public class MyJson<T> {
public List<T> posts;
public List<T> getPosts() {
return posts;
}
}
したがって、List<MyObject>
をデシリアライズする場合は、次のようにメソッドを呼び出します。
// assuming no Void parameters were required
MyJson<MyObject> myJson = doInBackground(MyObject.class);
やってみました?
gson.create().fromJson(reader, MyJson.class);
[〜#〜] edit [〜#〜]
this postを読んだ後、Type
の使用は正しいようです。あなたの問題はT
の使用だと思います。 Javaでは型消去があります。これは、実行時にT
のすべてのインスタンスがObject
に置き換えられることを覚えておく必要があります。 GSONを渡すのは本当にMyJson<Object>
です。<T>
の代わりに具体的なクラスでこれを試してみたら、うまくいくと思います。
したがって、試行錯誤の後、上記の答えは私にとってうまくいきませんでした、それが私のコードの終わりです:
public class AbstractListResponse<T> {
private List<T> result;
public List<T> getResult() {
return this.result;
}
}
ここで重要な部分は、左側の「<T>」を含むメソッドシグネチャです。
protected <T> AbstractListResponse<T> parseAbstractResponse(String json, TypeToken type) {
return new GsonBuilder()
.create()
.fromJson(json, type.getType());
}
Gsonを呼び出すと、メソッドは汎用オブジェクトのTypeTokenを受け取ります。
TypeToken<AbstractListResponse<MyDTO>> typeToken = new TypeToken<AbstractListResponse<MyDTO>>() {};
AbstractListResponse<MyDTO> responseBase = parseAbstractResponse(json, typeToken);
そして最後に、TypeTokenはMyDTOまたは単純なオブジェクトでさえMyDTOを使用できます。
私がやったようにコトリンと苦労している人のために、私はこのように働く方法を見つけました
val type = object : TypeToken<MyJson<MyObject>>() { }.type
val response = gson.fromJson<MyJson<MyObject>>(reader, type)
ジェネリック関数を呼び出すには、関数の名前の後に呼び出しサイトで型引数が必要であることに注意してください( here に表示)