是否可以使用jackson根据泛型的类设置元素的名称?
鉴于以下情况:
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>
反之亦然,浴室或所有其他可能的房间。是否可以让jackson在运行时从泛型的实际类派生元素名称?
答案 0 :(得分:0)
是的,您可以使用自定义序列化器根据通用类型设置元素名称。
请记住,杰克逊使用get
方法来命名序列化json / xml的属性,这就是为什么要在序列化xml上获取元素roomDetails
的原因。
像@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>