[英]Self circular reference in 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;
}
現在,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);
}
也許你可以試試這個:
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);
你會得到一個好結果。
這里出現了“魔術”: new TypeToken<Collection<Category>>() {}.getType()
整個代碼是:
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);
}
}
JSON文件是:
[
{
"childList":[
{
"childList":[
],
"id":110,
"Name":"Books",
"applicationCount":0
}
],
"id":110,
"name":"Books",
"applicationCount":0
}
]
看看GraphAdapterBuilder 。 您需要將其包含在您的應用中,但它可以序列化對象的任意圖形。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.