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