我正在连接到外部 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>
我想解析单个 Money
对象中的 currency
和 cost
元素。
更糟糕的是,内部item
仅指定成本并“重用”货币代码。我可以使用 Jackson 以某种智能方式解析它们吗?
最佳答案
I want to parse the currency and cost elements in a single Money object.
根据提供的 XML,您可以解析 currency
和cost
元素放入单个 Money
对象,通过为发票创建一个值对象并利用 @JsonUnwrapped
.
为发票创建值对象
如果您不想为发票创建对象,您可以配置 XmlMapper
忽略未知属性,并将整个响应反序列化为 Money
目的。在我看来,为发票创建一个单独的类是一种更简洁的方法。
创建Invoice
的目的object 是封装响应的所有元素。现在您可能只需要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;
}
}
the inner items only specify the cost and "reuse" the currency code.
分隔 Money
和“项目”模型(如果可能)
重用Money
与使用一个对象来表示每个 View 相比,两个不同模型的对象不太理想。例如,Money
对象 currency
和cost
,以及 Item
对象 id
, description
,和cost
。如果这在您的项目中是可能的,我将为“item”创建一个像这样的对象:
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
对于“项目”值
如果您没有自由创建新对象并且需要重用Money
,您可以配置您的XmlMapper
忽略未知属性并将所有属性放在 Money
上对象。
配置XmlMapper
忽略未知属性
我建议延长 XmlMapper
像这样:
public class CustomXmlMapper extends XmlMapper {
public CustomXmlMapper() {
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
}
将所有可能的属性添加到 Money
当元素存在时,这将填充属性。例如,当反序列化“item”时:id
, description
,和cost
将被填充并且 currency
将为空。
public class Money {
@JacksonXmlProperty(isAttribute = true)
public final String id;
public final String description;
private final String currency;
private final Double cost;
@JsonCreator
public Money(@JsonProperty("id") String id,
@JsonProperty("description") String description,
@JsonProperty("currency") String currency,
@JsonProperty("cost") Double cost) {
this.id = id;
this.description = description;
this.currency = currency;
this.cost = cost;
}
public String getId() {
return id;
}
public String getDescription() {
return description;
}
public String getCurrency() {
return currency;
}
public Double getCost() {
return cost;
}
}
关于java - 如何序列化/反序列化 "splashed"复杂类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30167770/