我正在连接外部XML API,我正在尝试使用Jackson XmlMapper
类将其解析为POJO。 XML的一部分如下所示:
<invoice>
<some>element</some>
<some_other>element</some_other>
<currency>USD</currency>
<cost>10.42</cost>
<breakdown>
<item id="1">
<description>blah blah</description>
<cost>4.21</cost>
</item>
</breakdown>
</invoice>
我想解析单个currency
对象中的cost
和Money
元素。
更糟糕的是,内部item
仅指定成本并“重复使用”货币代码。我可以使用杰克逊以一种聪明的方式解析它们吗?
答案 0 :(得分:4)
我想在单个Money对象中解析货币和成本要素。
根据提供的XML,您可以通过为发票创建值对象并使用@JsonUnwrapped
,将currency
和cost
元素解析为单个Money
对象。
如果您不想为发票创建对象,则可以将XmlMapper
配置为忽略未知属性,并将整个响应反序列化为Money
对象。在我看来,为您的发票创建一个单独的类是一种更清晰的方法。
创建Invoice
对象的目的是封装响应的所有元素。目前您可能只需要currency
和cost
,但稍后您可能需要访问breakdown
。该对象可以这样构造:
public class Invoice {
private final String some;
private final String some_other;
@JsonUnwrapped
private final Money money;
private final List<Item> breakdown;
@JsonCreator
public Invoice(@JsonProperty("some") String some,
@JsonProperty("some_other") String some_other,
@JsonProperty("money") Money money,
@JacksonXmlProperty(localName = "item") List<Item> breakdown) {
this.some = some;
this.some_other = some_other;
this.money = money;
this.breakdown = breakdown;
}
public String getSome() {
return some;
}
public String getSome_other() {
return some_other;
}
public Money getMoney() {
return money;
}
public List<Item> getBreakdown() {
return breakdown;
}
}
请注意,Money
属性已使用@JsonUnwrapped
进行注释。这可以在字段上,在构造函数内部或在setter上,它将“展开”Money
对象并在与Invoice
相同的级别上反序列化其成员。像这样构建您的类以将货币和成本反序列化为单个对象:
public class Money {
private final String currency;
private final Double cost;
@JsonCreator
public Money(@JsonProperty("currency") String currency,
@JsonProperty("cost") Double cost) {
this.currency = currency;
this.cost = cost;
}
public String getCurrency() {
return currency;
}
public Double getCost() {
return cost;
}
}
内部项目仅指定成本并“重复使用”货币代码。
Money
和“item”模型分开对于两个不同的模型重用Money
对象不太理想,因为有一个abject来表示每个视图。例如,Money
和currency
的{{1}}对象以及cost
,Item
和id
的{{1}}对象。如果你的项目可以做到这一点,我会为“item”创建一个这样的对象:
description
cost
作为“项目”值如果您没有自由创建新对象并需要重用public class Item {
@JacksonXmlProperty(isAttribute = true)
public final String id;
public final String description;
public final Double cost;
@JsonCreator
public Item(@JsonProperty("id") String id,
@JsonProperty("description") String description,
@JsonProperty("cost") Double cost) {
this.id = id;
this.description = description;
this.cost = cost;
}
public String getId() {
return id;
}
public String getDescription() {
return description;
}
public Double getCost() {
return cost;
}
}
,则可以将Money
配置为忽略未知属性并将所有属性放在{{1}上对象。
Money
以忽略未知属性我建议像这样扩展XmlMapper
:
Money
XmlMapper
这将在元素存在时填充属性。例如,当反序列化“项目”时:XmlMapper
,public class CustomXmlMapper extends XmlMapper {
public CustomXmlMapper() {
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
}
和Money
将被填充,id
将为空。
description