我有以下课程:
public class MeetingCenter {
private String name;
private List<MeetingRoom> meetingRoomList;
}
public class MeetingRoom {
private MeetingCenter meetingCenter;
private String code;
private String name;
private List<Reservation> reservationList;
}
public class Reservation {
private MeetingRoom meetingRoom;
private String owner;
}
我想使用以下架构创建JSON:
此方法在调用toJson()方法的行上引发异常:
private static void exportToJson(List<MeetingCenter> mcs) throws IOException {
Gson gson = new Gson();
String data = gson.toJson(mcs);
JsonWriter writer = new JsonWriter(new FileWriter("export.json"));
writer.setIndent(" "); // set indent
writer.beginObject(); // document start
writer.name("schema").value("PLUS4U.EBC.MCS.MeetingRoom_Schedule_1.0");
writer.name("uri").value("ues:UCL-BT:UCL.INF/DEMO_REZERVACE:EBC.MCS.DEMO/MR001/SCHEDULE");
writer.name("data").value(data);
writer.endObject(); // document end
writer.close();
}
例外:
Exception in thread "main" java.lang.StackOverflowError
at java.lang.StringBuffer.append(StringBuffer.java:380)
at java.io.StringWriter.write(StringWriter.java:77)
at com.google.gson.stream.JsonWriter.beforeName(JsonWriter.java:614)
at com.google.gson.stream.JsonWriter.writeDeferredName(JsonWriter.java:401)
at com.google.gson.stream.JsonWriter.beginArray(JsonWriter.java:287)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:95)
....
答案 0 :(得分:0)
您的所有对象都引用了其父母。
GSON查看MeetingCenter
,然后尝试序列化其子MeetingRoom
。 MeetingRoom
具有对MeetingCenter
的引用,因此GSON会绕圈绕圈,直到出现堆栈溢出为止。
要解决此问题,您可以确保只暴露孩子而不暴露父母。已经有很多问题表明了这一点。参见Java Gson Exclude fields during serialization。
例如,您的Reservation
可能看起来像这样:
class Reservation {
MeetingRoom meetingRoom;
@Expose
String owner;
}
我把剩下的交给你。
此外,您还可以在未启动数组的情况下调用writer.endArray()
。删除该行。
writer.beginObject(); // document start
writer.name("schema").value("PLUS4U.EBC.MCS.MeetingRoom_Schedule_1.0");
writer.name("uri").value("ues:UCL-BT:UCL.INF/DEMO_REZERVACE:EBC.MCS.DEMO/MR001/SCHEDULE");
writer.name("data").value(data);
//writer.endArray(); removed
writer.endObject(); // document end
writer.close();
答案 1 :(得分:0)
@Expose是避免stackoverflow异常的解决方案,但该语句
writer.name("data").value(data);
无效,因为数据将使用转义字符丰富。对于示例,您可以在数据字段中输入
"data": "{\"name\": \"center 1\" ... }"
所以反序列化阶段可能会有问题。
我的实现为MeetingCenter类提议了一个Container类,可以在其中配置架构和URI。
/** Container class configures the schema and URI */
public class Container {
@Expose
private String schema;
@Expose
private String uri;
@Expose
private List<MeetingCenter> data;
}
public class Reservation {
private MeetingRoom meetingRoom;
@Expose
private String owner;
}
public class MeetingRoom {
private MeetingCenter meetingCenter;
@Expose
private String code;
@Expose
private String name;
@Expose
private List<Reservation> reservationList;
}
public class MeetingCenter {
@Expose
private String name;
@Expose
private List<MeetingRoom> meetingRoomList;
}
public class Main {
public static void main(String[] args){
Container container = meetingCenterInitialization();
GsonBuilder builder = new GsonBuilder();
builder.setPrettyPrinting();
// it is necessary to avoid stackoverflow
builder.excludeFieldsWithoutExposeAnnotation();
Gson gson = builder.create();
String jsonString = gson.toJson(container);
System.out.println(jsonString);
Container container1 = gson.fromJson(jsonString, Container.class);
System.out.println("\n\n\n\n" + container1.getData().get(0).getName());
}
}
main方法的输出是
{
"schema": "PLUS4U.EBC.MCS.MeetingRoom_Schedule_1.0",
"uri": "ues:UCL-BT:UCL.INF/DEMO_REZERVACE:EBC.MCS.DEMO/MR001/SCHEDULE",
"data": [
{
"name": "center name",
"meetingRoomList": [
{
"code": "room 1",
...