Java xml unmarshalling list嵌套对象问题

时间:2017-11-29 18:44:19

标签: java xml

我的xml内容如下:

<ParentClass>
    <StringA>A</StringA>
    <StringB>B</StringB>
    <Items>
        <Item ts="2016-03-25T20:00:00+02:00">1.17</Item>
        <Item ts="2016-03-25T21:00:00+02:00">1.15</Item>
    </Items> 
</ParentClass>

我想阅读它,但我被困在正确的映射上。课程如下:

@XmlAccessorType(XmlAccessType.FIELD)
@NoArgsConstructor
@AllArgsConstructor
@Data
public class ParentClass {
    @XmlElement(name = "StringA", required = true)
    private String a;
    @XmlElement(name = "StringB", required = true)
    private String b;
    @XmlElement(name = "Items", required = true)
    private List<Item> consumptionList;

}

@NoArgsConstructor
@AllArgsConstructor
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class Item {
    @XmlAttribute(name = "ts", required = true)
    @XmlJavaTypeAdapter(value = LocalDateTimeAdapter.class)
    private LocalDateTime timestamp;
    private double value; //this corrensponds to 1.17 and 1.15 in xml
}

在实际文件中有100多个项目,当我读到它时,列表中只填充了一个Item类的实例,它的两个字段都为null。

我猜Item类中的映射都是错误的,但是尝试了所有,似乎没有任何工作。

我应该如何正确映射它以实现目标?

1 个答案:

答案 0 :(得分:2)

您需要将@XmlValue添加到字段value,否则默认为@XmlElement

此外,您需要将consumptionList上的注释更改为

@XmlElementWrapper(name = "Items")
@XmlElement(name = "Item", required = true)

另请注意,ts值为OffsetDateTime(或ZonedDateTime)值,而不是LocalDateTime,除非您LocalDateTimeAdapter应用了某个时区,例如: JVM默认时区。

我发现帮助正确应用@Xml...注释的最佳方法是创建对象并将它们编组为XML以查看您获得的内容。您当前的代码将创建此XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ParentClass>
    <StringA>A</StringA>
    <StringB>B</StringB>
    <Items ts="2016-03-25T20:00:00+02:00">
        <value>1.17</value>
    </Items>
    <Items ts="2016-03-25T21:00:00+02:00">
        <value>1.15</value>
    </Items>
</ParentClass>

如果您应用上述更改,则会获得:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ParentClass>
    <StringA>A</StringA>
    <StringB>B</StringB>
    <Items>
        <Item ts="2016-03-25T20:00:00+02:00">1.17</Item>
        <Item ts="2016-03-25T21:00:00+02:00">1.15</Item>
    </Items>
</ParentClass>

以上输出是通过添加以下代码创建的:

class LocalDateTimeAdapter extends XmlAdapter<String, LocalDateTime> {
    @Override
    public String marshal(LocalDateTime time) throws Exception {
        return time.atZone(ZoneOffset.ofHours(2))
                   .format(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssxxx"));
    }
    @Override
    public LocalDateTime unmarshal(String text) throws Exception {
        return ZonedDateTime.parse(text).toLocalDateTime();
    }
}
public static void main(String... args) throws Exception {
    ParentClass p = new ParentClass("A", "B", Arrays.asList(
            new Item(LocalDateTime.parse("2016-03-25T20:00:00"), 1.17),
            new Item(LocalDateTime.parse("2016-03-25T21:00:00"), 1.15)));

    JAXBContext jaxbContext = JAXBContext.newInstance(ParentClass.class);
    Marshaller marshaller = jaxbContext.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    marshaller.marshal(p, System.out);
}