Java “如何序列化/反序列化”;溅起;复杂类型?

Java “如何序列化/反序列化”;溅起;复杂类型?,java,xml,jackson,Java,Xml,Jackson,我正在连接到外部XMLAPI,并尝试使用JacksonXmlMapper类将其解析为POJO。XML的一部分如下所示: <invoice> <some>element</some> <some_other>element</some_other> <currency>USD</currency> <cost>10.42</cost> <brea

我正在连接到外部XMLAPI,并尝试使用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>

要素
要素
美元
10.42
废话
4.21
我想在一个
Money
对象中解析
currency
cost
元素

更糟糕的是,内部的
s只指定成本并“重用”货币代码。我可以使用Jackson以某种智能的方式解析它们吗

我想在一个Money对象中解析currency和cost元素

给定所提供的XML,您可以通过为发票创建一个值对象并使用它将
货币
成本
元素解析为单个
货币
对象

为发票创建值对象 如果不想为发票创建对象,可以将
XmlMapper
配置为忽略未知属性,并将整个响应反序列化为
Money
对象。在我看来,为发票创建一个单独的类是一种更干净的方法

创建
Invoice
对象的目的是封装响应的所有元素。现在您可能只需要
货币
成本
,但稍后您可能需要访问
细分
。对象的结构可以如下所示:

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
对象不如用一个对象来表示每个视图。例如,
Money
对象用于
currency
cost
,而
Item
对象用于
id
description
cost
。如果这在您的项目中是可能的,我会为“item”创建一个类似这样的对象:

重新使用
货币
获取“项目”值 如果您无权创建新对象,并且需要重新使用
Money
,则可以将
XmlMapper
配置为忽略未知属性,并将所有属性放在
Money
对象上

配置
XmlMapper
忽略未知属性 我建议像这样扩展
XmlMapper

public class CustomXmlMapper extends XmlMapper {
    public CustomXmlMapper() {
        configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }
}
将所有可能的属性添加到
Money
当元素存在时,这将填充属性。例如,当“项目”被反序列化时:
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;
    }
}

妙极了!谢谢
public class CustomXmlMapper extends XmlMapper {
    public CustomXmlMapper() {
        configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }
}
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;
    }
}