将XML解析为Java对象节点

3

我在尝试将XML文档解析为Java对象时遇到了问题。我只需要保留iidtime列表中的必要信息。

XML测试文件:

    <items>
       <item>
        <iid>14</iid>
          <options>
              <option>
                <times>
                  <time>
                   <timeentry>20200714100100</timeentry>                           
                   <timetill>20200714101500</timetill>
                   <timemaxcount>2</timemaxcount>
                  </time>
                  <time>
                   <timeentry>20200714101600</timeentry>
                   <timetill>20200714103000</timetill>
                   <timemaxcount>2</timemaxcount>
                  </time>
                 <time>
                  <timeentry>20200714103100</timeentry>
                  <timetill>20200714104500</timetill>
                  <timemaxcount>2</timemaxcount>
                 </time>
                 <time>
                  <timeentry>20200714104600</timeentry>
                  <timetill>20200714110000</timetill>
                  <timemaxcount>2</timemaxcount>
                  </time
              </option>
          </options>
         </item>
      </items>

我创建了两个Java对象类,它们包含iid和时间列表。当解析xml文件时,只有iid字段填充,而列表对象为空。我错过了什么吗?

@JsonIgnoreProperties(ignoreUnknown = true)
@XmlRootElement(name = "item")
@JacksonXmlRootElement(localName = "item")
public class SubProduct implements Serializable {

    private String iid;

    @JacksonXmlElementWrapper(localName = "times")
    @JacksonXmlProperty(localName = "time")
    private List<TimePeriod> times;
}

@JsonIgnoreProperties(ignoreUnknown = true)
@JacksonXmlRootElement(localName = "time")
public class TimePeriod implements Serializable {
    @JsonProperty(value = "timeentry")
    String timeEntry;
    @JsonProperty(value = "timetill")
    String timeTill;
    @JsonProperty(value = "timemaxcount")
    String timeMaxCount;
}

服务层:

...
NodeList itemList = document.getElementsByTagName("item"); 
List<SubProduct> subProducts = new ArrayList<>();
        for (int i = 0; i < nodes.getLength(); i++) {
            SubProduct value = xmlMapper.readValue(nodeToString(nodes.item(i)), SubProduct.class);
            subProducts.add(value);
            
        }
        return subProducts;

...

 public static String nodeToString(Node node) throws Exception{
        StringWriter sw = new StringWriter();

        Transformer t = TransformerFactory.newInstance().newTransformer();
        t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        t.setOutputProperty(OutputKeys.INDENT, "yes");
        t.transform(new DOMSource(node), new StreamResult(sw));

        return sw.toString();
    }

reponse:

   {
        "iid": "9",
        "times": null
    },
1个回答

1
你不需要将JacksonJAXBTransformer类混合使用。你可以直接将给定的XML负载反序列化为POJO模型。itemsoptionstimes节点代表节点列表。我们可以将它们映射到以下模型中:
@Data
@ToString
class Item {
    private int iid;
    private List<Option> options;
}

@Data
@ToString
class Option {

    private List<Time> times;
}

@Data
@ToString
class Time {

    @JsonFormat(pattern = "yyyyMMddHHmmss")
    @JsonProperty("timeentry")
    private LocalDateTime entry;

    @JsonFormat(pattern = "yyyyMMddHHmmss")
    @JsonProperty("timetill")
    private LocalDateTime till;

    @JsonProperty("timemaxcount")
    private int maxCount;
}

我使用Lombok注解来避免样板代码。使用方法简单:

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.Data;
import lombok.ToString;

import java.io.File;
import java.time.LocalDateTime;
import java.util.List;

public class XmlMapperApp {

    public static void main(String... args) throws Exception {
        File xmlFile = new File("./resource/test.xml").getAbsoluteFile();

        XmlMapper mapper = XmlMapper.xmlBuilder()
                .addModule(new JavaTimeModule())
                .build();
        List<Item> items = mapper.readValue(xmlFile, new TypeReference<List<Item>>() {
        });
        items.forEach(item -> {
            System.out.println("Id => " + item.getIid());
            System.out.println("Times => ");
            item.getOptions().stream().flatMap(o -> o.getTimes().stream())
                    .forEach(System.out::println);
        });
    }
}

上面的代码打印出:
Id => 14
Times => 
Time(entry=2020-07-14T10:01, till=2020-07-14T10:15, maxCount=2)
Time(entry=2020-07-14T10:16, till=2020-07-14T10:30, maxCount=2)
Time(entry=2020-07-14T10:31, till=2020-07-14T10:45, maxCount=2)
Time(entry=2020-07-14T10:46, till=2020-07-14T11:00, maxCount=2)

另请参阅:


1
直接反序列化对我来说很好用,没有那些花里胡哨的框架 :) - Eltomon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接