У меня возникли проблемы с десериализацией массива 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;
}
Итак, Гсон явно жалуется на циклическую ссылку. Есть ли способ проанализировать этот ввод 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);
}