Как десериализовать массив объектов, используя gson и JsonWriter - PullRequest
0 голосов
/ 29 января 2019

У меня есть следующие классы:

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 со следующей схемой:

Schema

Этот метод вызывает исключение в строке, где я вызываю метод 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)
    ....

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

@Expose - это решение, позволяющее избежать исключения stackoverflow, но оператор

writer.name("data").value(data);

недопустим, поскольку данные будут обогащены escape-символом.Например, вы можете указать в поле данных

"data": "{\"name\": \"center 1\" ... }"

, что может вызвать проблемы на этапе десериализации.

Моя реализация предлагает класс Container для класса MeetingCenter, где схема и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());
    }
}

Выход основного метода:

{
  "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",

         ...
0 голосов
/ 29 января 2019

Все ваши объекты имеют ссылки на своих родителей.

GSON просматривает MeetingCenter, а затем пытается сериализовать своих дочерних MeetingRoom s.MeetingRoom s имеют ссылку обратно на MeetingCenter, поэтому GSON вращается и кружится по кругу, пока вы не получите переполнение стека.

Чтобы исправить это, вы можете убедиться, что выставляете только детей, а неродители.Есть много вопросов, показывающих это уже.См. Java Gson Исключить поля во время сериализации .

Например, ваш 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...