我正在尝试使用Gson反序列化Reddit评论页面,但我得到了StackOverflowError
。从我发现谷歌搜索,这是因为JSON数据中的循环引用。数据有嵌套对象,如下所示。
Listing:{
data:List<Comment>
}
Comment:{
...
replies:Listing
}
我不确定如何编写解串器来处理这类数据。
有人可以帮助我使用Gson处理上面的数据吗?
以下是JSON数据的示例网址之一:enter image description here
编辑1:
我已根据@Lyubomyr Shaydariv的建议创建了类型适配器。以下是我的新代码。
我还无法找到优化嵌套交换机案例的方法。新代码没有给出任何错误但没有返回任何结果。
public static void main(String[] args) {
GsonBuilder gb = new GsonBuilder();
gb.registerTypeAdapter(Thing.class, new ThingDeserializer());
gb.registerTypeAdapter(Comment.class, new CustomAdapter());
Gson gson = gb.create();
try {
List<Listing> listing = gson.fromJson(readUrlToString("https://www.reddit.com/r/technology/comments/6977qb/.json"), new TypeToken<Collection<Listing>>() {}.getType());
System.out.println(listing);
} catch (Exception e) {
e.printStackTrace();
}
}
public class Listing {
private ListingData data;
}
public class ListingData {
private List<Child> children = null;
}
public class Child {
private Thing data;
}
public class Comment implements Thing {
private Listing replies;
}
public class ThingDeserializer implements JsonDeserializer<Thing> {
@Override
public Thing deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json == null)
return null;
else {
Thing thing =null;
String name=json.getAsJsonObject().get("name").getAsJsonPrimitive().getAsString();
if(name.startsWith("t1_")){
thing=context.deserialize(json,new TypeToken<Comment>(){}.getType());
}
else if(name.startsWith("t2_")){
thing=context.deserialize(json,new TypeToken<User>(){}.getType());
}
else if(name.startsWith("t3_")){
thing=context.deserialize(json,new TypeToken<Post>(){}.getType());
}
else if(name.startsWith("t4_")){
thing=context.deserialize(json,new TypeToken<Message>(){}.getType());
}
else if(name.startsWith("t5_")){
thing=context.deserialize(json,new TypeToken<Subreddit>(){}.getType());
}
return thing;
}
}
}
public class CustomAdapter extends TypeAdapter<Comment> {
@Override
public Comment read(JsonReader jsonReader) throws IOException {
Comment comment=new Comment();
jsonReader.beginObject();
while(jsonReader.hasNext()) {
if (jsonReader.peek().equals(JsonToken.NAME)) {
switch (jsonReader.nextName()) {
case "replies":
if (jsonReader.peek().equals(JsonToken.BEGIN_OBJECT)) {
jsonReader.beginObject();
Listing listing = new Listing();
while (jsonReader.hasNext()) {
switch (jsonReader.nextName()) {
case "kind":
listing.setKind(jsonReader.nextString());
break;
case "data":
ListingData listingData = new ListingData();
jsonReader.beginObject();
while (jsonReader.hasNext()) {
switch (jsonReader.nextName()) {
case "children":
jsonReader.beginArray();
List<Child> childList = new ArrayList<>();
while (jsonReader.hasNext()) {
jsonReader.beginObject();
Child child = new Child();
while (jsonReader.hasNext()) {
switch (jsonReader.nextName()) {
case "data":
child.setData(read(jsonReader));
break;
default:
jsonReader.skipValue();
break;
}
}
childList.add(child);
}
listingData.setChildren(childList);
break;
default:
jsonReader.skipValue();
break;
}
}
listing.setData(listingData);
break;
default:
jsonReader.skipValue();
break;
}
}
comment.setReplies(listing);
}
break;
default:
jsonReader.skipValue();
break;
}
}
}
return comment;
}
}