【问题标题】:Parsing XML to Java Object Node将 XML 解析为 Java 对象节点
【发布时间】:2020-06-29 20:48:42
【问题描述】:

目前我在尝试将 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>

我创建了两个包含 iid 和时间列表的 Java Objects 类。解析 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();
    }

回复:

   {
        "iid": "9",
        "times": null
    },

【问题讨论】:

    标签: java xml parsing jackson jackson-dataformat-xml


    【解决方案1】:

    您无需将JacksonJAXBTransformer 类混合使用。您可以将给定的XML 有效负载直接反序列化为POJO 模型。 itemsoptionstimes 节点代表 List 个节点。我们可以将其映射到以下模型:

    @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)
    

    另见:

    【讨论】:

    • 感谢您的建议。没有花哨的框架,直接反序列化对我来说很好:)
    猜你喜欢
    • 2016-12-02
    • 2012-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-29
    • 2013-04-28
    • 1970-01-01
    相关资源
    最近更新 更多