序列化列表生成的“项目”节点

问题描述

我是一个相当简单的java对象模型。一个预订等级有一个酒店列表作为成员。 (简化源)

class Booking {
  private Integer bookingId;
  private List<Hotel> hotels;
}

我想通过为每个班级使用 StdSerailizer 将预订序列化为 XML。

public class HotelTransform extends StdSerializer<Hotel> {

    protected HotelTransform(Class<Hotel> t) {
        super(t);
    }

    private static final long serialVersionUID = 4102379614389258553L;

    @Override
    public void serialize(Hotel value,JsonGenerator gen,SerializerProvider provider) throws IOException {
        gen.writeStartObject();        
        gen.writeStringField("HName",value.getHotelName());
        gen.writeStringField("Start",value.m_startDateLocal.toString());
        gen.writeStringField("End",value.m_startDateLocal.toString());
        gen.writeEndobject();
    } 
}
public class BookingTransform extends StdSerializer<Booking> {

    protected BookingTransform(Class<Booking> t) {
        super(t);
    }

    @Override
    public void serialize(Booking value,SerializerProvider provider) throws IOException {
        
        gen.writeStartObject();        
        gen.writeObjectField("Entries",value.getBookBookingEntry());
        gen.writeEndobject();

    }
}

序列化本身是通过以下测试代码完成的

public void simpleSmoketest() {

        Booking booking = new Booking();
        booking.setBookingId(99);

        Hotel aHotel = new Hotel();
        aHotel.setHotelName("HEHotel");
        aHotel.setStartDateLocal(LocalDateTime.Now());
        aHotel.setEndDateLocal(LocalDateTime.Now());
        booking.addhotel(aHotel);

        Hotel aHotel2 = new Hotel();
        aHotel2.setHotelName("HEHotel2");
        aHotel2.setStartDateLocal(LocalDateTime.Now());
        aHotel2.setEndDateLocal(LocalDateTime.Now());
        booking.addhotel(aHotel2);

        ObjectMapper mapper = new XmlMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(new BookingTransform(Booking.class));
        module.addSerializer(new HotelTransform(Hotel.class));
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.registerModule(module);

        try {
            String serialized = mapper.writeValueAsstring(booking);
            m_logger.debug("Serialized to: " + serialized);
        } catch (JsonProcessingException e) {
            e.printstacktrace();
        }
    }

生成输出为:

<Booking>
  <Entries>
    <item>
      <HName>HEHotel</HName>
      <Start>2020-12-29T01:43:18.008480</Start>
      <End>2020-12-29T01:43:18.008480</End>
    </item>
    <item>
      <HName>HEHotel2</HName>
      <Start>2020-12-29T01:43:18.009463</Start>
      <End>2020-12-29T01:43:18.009463</End>
    </item>
  </Entries>
</Booking>

这已经接近我想要的了,但我不希望将我的酒店列表中的条目命名为“项目”,我希望将它们命名为“酒店”。像这样:

<Booking>
  <Entries>
    <Hotel>
      <HName>HEHotel</HName>
      <Start>2020-12-29T01:43:18.008480</Start>
      <End>2020-12-29T01:43:18.008480</End>
    </Hotel>
    <Hotel>
      <HName>HEHotel2</HName>
      <Start>2020-12-29T01:43:18.009463</Start>
      <End>2020-12-29T01:43:18.009463</End>
    </Hotel>
  </Entries>
</Booking>

我真的尝试了很多东西,没有。没有成功。 谁能解释我如何解决这个问题? 顺便说一句,在我的 POJO 中使用注释是没有选择的。

亲切的问候 哈里·E。

解决方法

我认为这个问题是因为在 JSON 和 XML 中处理数组的方式不同。

以下是来自 forall a. c a => () -> b 的片段:

import ast
def get_queryset(self):
    queryset = super().get_queryset()
    search = self.request.GET.get('type')
    # need to convert search as list of tuple
    search = ast.literal_eval(search)

因此在 XML 的情况下,每个数组元素都被视为一个对象,默认字段名称为 item


当前用例的一种选择是使用特定于 XML 的 XMLSerializerProvider._startRootArray(),并在其中手动序列化 protected void _startRootArray(ToXmlGenerator xgen,QName rootName) throws IOException { xgen.writeStartObject(); // Could repeat root name,but what's the point? How to customize? xgen.writeFieldName("item"); } ,如下所示:

Transformer

注意:如果您将此序列化程序用于 JSON,将导致对象 List 中名为 @Override public void serialize(Booking value,JsonGenerator gen,SerializerProvider provider) throws IOException { gen.writeStartObject(); gen.writeFieldName("Entries"); gen.writeStartObject(); for (Hotel hotel : value.getBookBookingEntry()) { gen.writeFieldName("Hotel"); gen.writeObject(hotel); } gen.writeEndObject(); gen.writeEndObject(); } 的重复字段。