この形式に従うJson配列を逆シリアル化するのにいくつかの問題があります:
[
{
"ChildList":[
{
"ChildList":[
],
"Id":110,
"Name":"Books",
"ApplicationCount":0
}
],
"Id":110,
"Name":"Books",
"ApplicationCount":0
}
]
これは基本的にカテゴリの配列であり、各カテゴリにはサブカテゴリのリストなども含めることができます。私のクラスモデルは次のようになります。
public class ArrayOfCategory{
protected List<Category> category;
}
public class Category{
protected ArrayOfCategory childList;
protected int id;
protected String name;
protected int applicationCount;
}
さて、Gsonは明らかに循環参照について不平を言っています。カテゴリのレベルがいくつあるかを推測できない場合、このJson入力を解析する方法はありますか?前もって感謝します。
編集: 誰かが同様の問題を抱えている場合に備えて、Spaethの回答に基づいて、リフレクションを使用してソリューションをより一般的なケースに適合させました。唯一の要件は、JSON配列で表されるオブジェクトのリストが別のクラス(私の例ではCategoryやArrayOfCategoryなど)にラップされていることです。次のコードを元のサンプルに適用すると、「deserializeJson(jsonString、ArrayOfCategory.class)」を呼び出すだけで、期待どおりに機能します。
private <T> T deserializeJson(String stream, Class<T> clazz) throws PluginException {
try {
JsonElement je = new JsonParser().parse(stream);
if (je instanceof JsonArray) {
return deserializeJsonArray(clazz, je);
} else {
return new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create().fromJson(stream, clazz);
}
} catch (Exception e) {
throw new PluginException("Failed to parse json string: " + ((stream.length() > 20) ? stream.substring(0, 20) : stream) + "... to class " + clazz.getName());
}
}
private <T> T deserializeJsonArray(Class<T> clazz, JsonElement je) throws InstantiationException, IllegalAccessException {
ParameterizedType listField = (ParameterizedType) clazz.getDeclaredFields()[0].getGenericType();
final Type listType = listField.getActualTypeArguments()[0];
T ret = clazz.newInstance();
final Field retField = ret.getClass().getDeclaredFields()[0];
retField.setAccessible(true);
retField.set(ret, getListFromJsonArray((JsonArray) je,(Class<?>) listType));
return ret;
}
private <E> List<E> getListFromJsonArray(JsonArray je, Class<E> listType) {
Type collectionType = new TypeToken<List<E>>(){}.getType();
final GsonBuilder builder = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE);
Gson jsonParser = builder.create();
return jsonParser.fromJson(je, collectionType);
}