Самостоятельная циклическая ссылка в Gson

У меня возникли проблемы с десериализацией массива 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);
}
6
задан jlordiales 16 June 2012 в 14:13
поделиться