У меня возникли некоторые проблемы с десериализации массив JSON, который имеет следующий формат:Само циклическая ссылка в Gson
[
{
"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, учитывая, что я не могу предположить, сколько уровней категорий есть? Спасибо заранее.
Edit: Только в случае, если кто-то имеет такую же проблему, на основе Спаета ответ я приспособил решение в более общем случае, с помощью отражения. Единственное требование состоит в том, что список объектов, представленных массивом 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);
}
Спасибо. Тип TypeToken работал отлично, хотя мне пришлось немного адаптировать ваш ответ к моему делу, поскольку ArrayOfCategory и Category были всего лишь одним примером, но мне пришлось рассмотреть более общий случай. Если вам интересно, я обновил свой вопрос. Cheers – jlordiales