java - 将 XML 解析为 Java 对象节点

标签 java xml parsing jackson jackson-dataformat-xml

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

最佳答案

您不需要将 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)

另见:

关于java - 将 XML 解析为 Java 对象节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62646439/

相关文章:

Ruby 字符串整数扫描

c# - 第一次机会异常(exception)是什么意思

Android工具栏主页按钮不显示

json - 如何解析: kubectl get pods using jsonpath的json格式输出

java - ItemReader 返回一个包含整行作为字符串的 FlatFileItemReader

java - logback.xml 文件未加载

java - 二维 ArrayList 初始化行

java - 我可以终止等待 TCP 连接进入的线程吗?

java - Android - 当我重新启动应用程序时,SharedPreferences 没有保存

java - 如果字符串实际上是数字,则将百分比符号 (%) 附加到字符串