Java Gson中的自循环参考

Java Gson中的自循环参考,java,json,gson,circular-reference,Java,Json,Gson,Circular Reference,我在反序列化遵循以下格式的Json数组时遇到了一些问题: [ { "ChildList":[ { "ChildList":[ ], "Id":110, "Name":"Books", "ApplicationCount":0 } ], "Id":110, "Name":"Books", "ApplicationCount":0 } ] 它基本上是一个类别数组,其中每个类别还

我在反序列化遵循以下格式的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;
}
公共类ArrayOfCategory{
受保护名单类别;
}
公共类类别{
受保护的ArrayOfCategory子列表;
受保护的int-id;
受保护的字符串名称;
受保护的int应用程序计数;
}
现在,格森显然在抱怨循环引用。考虑到我无法假设有多少级别的类别,有没有办法解析这个Json输入? 提前谢谢

编辑: 以防有人有类似的问题,根据斯佩思的回答,我使用反射将解决方案调整为更一般的情况。唯一的要求是由JSON数组表示的对象列表包装在另一个类中(如我的示例中的Category和ArrayOfCategory)。将下面的代码应用到我的原始示例中,您只需调用“反序列化JSON(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);
}
private T反序列化JSON(字符串流,类clazz)抛出PluginException{
试一试{
JsonElement je=新的JsonParser().parse(流);
if(JsonArray的je实例){
返回反序列化jsonarray(clazz,je);
}否则{
返回新的GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create().fromJson(stream,clazz);
}
}捕获(例外e){
抛出新的PluginException(“未能解析json字符串:+((stream.length()>20)?stream.substring(0,20):stream)+“…到类”+clazz.getName());
}       
}
私有T反序列化JSONArray(clazz类,JsonElement je)抛出实例化异常,IllegalAccessException{
ParameteredType listField=(ParameteredType)clazz.getDeclaredFields()[0]。getGenericType();
最终类型listType=listField.getActualTypeArguments()[0];
T ret=clazz.newInstance();
最终字段retField=ret.getClass().getDeclaredFields()[0];
retField.setAccessible(true);
set(ret,getListFromJsonArray((JsonArray)je,(Class)listType));
返回ret;
}
私有列表getListFromJsonArray(JsonArray je,类listType){
Type collectionType=new-TypeToken(){}.getType();
最终GsonBuilder=new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER\u CAMEL\u大小写);
Gson jsonParser=builder.create();
返回jsonParser.fromJson(je,collectionType);
}

也许你可以试试这个:

    com.google.gson.Gson gson = new GsonBuilder().create();
    InputStreamReader reader = new InputStreamReader(new FileInputStream(new File("/tmp/gson.txt")));
    Collection<Category> fromJson = gson.fromJson(reader, new TypeToken<Collection<Category>>() {}.getType());
    System.out.println(fromJson);

看一看。您需要将其包含在应用程序中,但它可以序列化任意对象的图形。

事实证明,您并不需要GraphAdapterBuilder进行反序列化,而只需要进行序列化(至少在我的情况下是这样)。无论如何,谢谢你给我指了一个有趣而且可能有用的图书馆。谢谢。虽然ArrayOfCategory和Apple仅仅是一个例子,但我不得不考虑一个更一般的情况,但是这个类型的东西工作得很好,尽管我不得不把你的答案稍加修改,以适应我的情况。如果你好奇,我更新了我的问题。干杯
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.List;

import com.google.gson.GsonBuilder;
import com.google.gson.JsonIOException;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;

public class GsonCircularReference {

    public class Category {
        protected List<Category> childList;
        protected int id;
        protected String name;
        protected int applicationCount;

        public List<Category> getChildList() {
            return childList;
        }

        public void setChildList(final List<Category> childList) {
            this.childList = childList;
        }

        public int getId() {
            return id;
        }

        public void setId(final int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(final String name) {
            this.name = name;
        }

        public int getApplicationCount() {
            return applicationCount;
        }

        public void setApplicationCount(final int applicationCount) {
            this.applicationCount = applicationCount;
        }

        @Override
        public String toString() {
            return "Category [category=" + childList + ", id=" + id + ", name=" + name + ", applicationCount="
                    + applicationCount + "]";
        }

    }

    public static void main(final String[] args) throws JsonSyntaxException, JsonIOException, FileNotFoundException {
        com.google.gson.Gson gson = new GsonBuilder().create();
        InputStreamReader reader = new InputStreamReader(new FileInputStream(new File("/tmp/gson.txt")));
        Collection<Category> fromJson = gson.fromJson(reader, new TypeToken<Collection<Category>>() {}.getType());
        System.out.println(fromJson);
    }

}
[
{
  "childList":[
     {
        "childList":[
        ],
        "id":110,
        "Name":"Books",
        "applicationCount":0
     }
  ],
  "id":110,
  "name":"Books",
  "applicationCount":0
}
]