Джексон установил имя элемента в зависимости от универсального типа - PullRequest
0 голосов
/ 22 сентября 2018

Можно ли, используя Джексона, установить имя элемента в зависимости от класса универсального элемента?

Учитывая следующий сценарий:

public class Room<T> {
    private int roomId;
    private String roomName;
    private T roomDetails;
//constructor getters, setters
}

public class Livingroom {
    private boolean hasCouch;
    private int numOfSeats;
//constructor getters, setters
}

public class Bathroom{
    private boolean hasShower;
    private boolean hasSink;
//constructor getters, setters
}

Если я использую Джексона длясериализовать объект комнаты (с общей гостиной), он выглядит следующим образом:

public void jackson() throws JsonProcessingException {
    Livingroom livingroom = new Livingroom();
    livingroom.setHasCouch(true);
    livingroom.setNumOfSeats(5);

    Room<Livingroom> room = new Room<>();
    room.setRoomDetails(livingroom);
    room.setRoomId(10);
    room.setRoomName("MyRoom");
    XmlMapper xmlMapper = new XmlMapper();
    String xml = xmlMapper.writeValueAsString(room);
    System.out.println(xml);
}

В результате получается:

<Room>
    <roomId>10</roomId>
    <roomName>MyRoom</roomName>
    <roomDetails>
        <hasCouch>true</hasCouch>
        <numOfSeats>5</numOfSeats>
    </roomDetails>
</Room>

Как бы я хотел, чтобы результат выгляделэто:

<Room>
    <roomId>10</roomId>
    <roomName>MyRoom</roomName>
    <Livingroom>
        <hasCouch>true</hasCouch>
        <numOfSeats>5</numOfSeats>
    </Livingroom>
</Room>

И наоборот для ванной комнаты или всех других возможных комнат.Можно ли позволить Джексону получить имя элемента из фактического класса универсального во время выполнения?

1 Ответ

0 голосов
/ 23 сентября 2018

Да, вы можете установить имя элемента в зависимости от универсального типа с помощью пользовательского сериализатора .

Имейте в виду, что Джексон использует методы get для именования свойствсериализованный json / xml, поэтому вы получаете элемент roomDetails в вашем сериализованном xml.

Аннотации типа @JsonGetter и @JsonProperty ожидают постоянного значения, поэтому их нельзя использовать в этом случае, потому что мыможно просто определить тип во время выполнения.

Решение:

Room класс, помеченный @JsonSerialize:

@JsonSerialize(using = RoomSerializer.class)
public class Room<T> {
    private int roomId;
    private String roomName;
    private T roomDetails;

    public int getRoomId() {
        return roomId;
    }

    public void setRoomId(int roomId) {
        this.roomId = roomId;
    }

    public String getRoomName() {
        return roomName;
    }

    public void setRoomName(String roomName) {
        this.roomName = roomName;
    }

    public T getRoomDetails() {
        return roomDetails;
    }

    public void setRoomDetails(T roomDetails) {
        this.roomDetails = roomDetails;
    }
}

Классы типа Bathroom и Livingroom остаются неизменными.

RoomSerializer реализация:

public class RoomSerializer extends StdSerializer<Room> {

    public RoomSerializer() {
        this(null);
    }

    public RoomSerializer(Class<Room> t) {
        super(t);
    }

    @Override
    public void serialize(Room value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        jgen.writeStartObject();
        jgen.writeNumberField("roomId", value.getRoomId());
        jgen.writeStringField("roomName", value.getRoomName());

        // Here we determine the field name depending on the type
        String roomDetailsFieldName = value.getRoomDetails().getClass().getSimpleName();
        jgen.writeObjectField(roomDetailsFieldName, value.getRoomDetails());

        jgen.writeEndObject();
    }
}

И с вашим примером вы получите то, что вы желаете:

<Room>
    <roomId>10</roomId>
    <roomName>MyRoom</roomName>
    <Livingroom>
        <hasCouch>true</hasCouch>
        <numOfSeats>5</numOfSeats>
    </Livingroom>
</Room>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...