将 XML 解析为 Java 对象节点
Parsing XML to Java Object Node
目前我在尝试将 xml 文档解析为 Java 对象时遇到问题。我想保留的唯一必要信息是 iid 和 time 列表。
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();
}
回复:
{
"iid": "9",
"times": null
},
您不需要将 Jackson
与 JAXB
或 Transformer
class 混用。您可以直接将给定的 XML
有效负载反序列化为 POJO
模型。 items
、options
和 times
个节点代表 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)
另请参阅:
目前我在尝试将 xml 文档解析为 Java 对象时遇到问题。我想保留的唯一必要信息是 iid 和 time 列表。
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();
}
回复:
{
"iid": "9",
"times": null
},
您不需要将 Jackson
与 JAXB
或 Transformer
class 混用。您可以直接将给定的 XML
有效负载反序列化为 POJO
模型。 items
、options
和 times
个节点代表 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)
另请参阅: