Parsing XML to Java Object Node

无人久伴 提交于 2021-01-03 06:44:45

问题


Currently I'am facing problem when trying to parse a xml document to a Java Object. The only necessary information which i want to keep is the iid and time list.

xml test file:

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

I have created two Java Objects classes which contains the iid and the time list. When parsing the xml file only the field iid gets filled and the list object is null. What do I missing ?

@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;
}

service layer:

...
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:


You do not need to mix Jackson with JAXB or Transformer class. You can directly deserialise given XML payload to POJO model. items, options and times nodes represent List of nodes. We can map the to below model:

@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;
}

I used Lombok annotations to avoid boilerplate code. Simple usage:

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);
        });
    }
}

Above code prints:

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)

See also:

  • Java 8 flatMap example
  • jackson-modules-java8


来源:https://stackoverflow.com/questions/62646439/parsing-xml-to-java-object-node

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!