java - 使用 Jaxb 解码嵌套 Map

标签 java xml jaxb

我需要以下 DTO

@XmlRootElement(name = "exchangerate")
@XmlAccessorType(XmlAccessType.FIELD)
public class ExchRates {

    @XmlJavaTypeAdapter(DateAdapter.class)
    private Date date;

    @XmlJavaTypeAdapter(JaxbExchangeRatesMapAdapter.class)
    private Map<CurrencyUnit, Map<CurrencyUnit, Double>> rates = new HashMap<>();
}

如何将此 xml 解码到上面的 DTO 中?

<exchangerate>
    <date>2015-05-04</date>
    <EUR>
        <EUR>1</EUR>
        <GBP>0.73788</GBP>
        <USD>1.1152</USD>
    </EUR>
    <GBP>
        <EUR>1.35523</EUR>
        <GBP>1</GBP>
        <USD>1.51136</USD>
    </GBP>
    <USD>
        <EUR>0.8967</EUR>
        <GBP>0.66166</GBP>
        <USD>1</USD>
    </USD>
</exchangerate>

我阅读了一些教程和示例,但我发现没有一个所有键都是 xml 的节点值。

编辑

几个小时后,我已经接近解决方案了。

我的 XmlAdapter:

public class JaxbExchangeRatesMapAdapter extends XmlAdapter<JaxbExchangeRatesMap, Map<CurrencyUnit, Map<CurrencyUnit, Double>>> {

    @Override
    public Map<CurrencyUnit, Map<CurrencyUnit, Double>> unmarshal(JaxbExchangeRatesMap v) throws Exception {
        return null;
    }

    @Override
    public JaxbExchangeRatesMap marshal(Map<CurrencyUnit, Map<CurrencyUnit, Double>> v) throws Exception {
        JaxbExchangeRatesMap map = new JaxbExchangeRatesMap();

        for (CurrencyUnit currencyFrom : v.keySet()) {
            Map<CurrencyUnit, Double> from = v.get(currencyFrom);
            JaxbExchangeRatesEntry entry = new JaxbExchangeRatesEntry();
            for (CurrencyUnit currencyTo : from.keySet()) {
                entry.getEntries().add(new JAXBElement<>(new QName(currencyTo.getCurrencyCode()), Double.class, from.get(currencyTo)));
            }
            JAXBElement<JaxbExchangeRatesEntry> jaxbElement = new JAXBElement<>(new QName(currencyFrom.getCurrencyCode()), JaxbExchangeRatesEntry.class, entry);
            map.getEntires().add(jaxbElement);
        }
        return map;
    }

}

以及我的映射类:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso(JaxbExchangeRatesEntry.class)
public class JaxbExchangeRatesMap extends Printable {

    private static final long serialVersionUID = 15543456767150881L;

    @XmlAnyElement
    private List<JAXBElement<JaxbExchangeRatesEntry>> entires = new ArrayList<>();

    public List<JAXBElement<JaxbExchangeRatesEntry>> getEntires() {
        return entires;
    }

    public JaxbExchangeRatesMap setEntires(List<JAXBElement<JaxbExchangeRatesEntry>> entires) {
        this.entires = entires;
        return this;
    }
}

@XmlAccessorType(XmlAccessType.FIELD)
public class JaxbExchangeRatesEntry extends Printable {

    private static final long serialVersionUID = -694282168028218725L;

    @XmlAnyElement
    private List<JAXBElement<Double>> entries = new ArrayList<>();

    public List<JAXBElement<Double>> getEntries() {
        return entries;
    }

    public JaxbExchangeRatesEntry setEntries(List<JAXBElement<Double>> entries) {
        this.entries = entries;
        return this;
    }
}

这样我得到了以下结果:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<exchangerate>
    <rates>
        <USD>
            <USD>9.0</USD>
            <EUR>7.0</EUR>
            <GBP>8.0</GBP>
        </USD>
        <EUR>
            <USD>3.0</USD>
            <EUR>1.0</EUR>
            <GBP>2.0</GBP>
        </EUR>
        <GBP>
            <USD>6.0</USD>
            <EUR>4.0</EUR>
            <GBP>5.0</GBP>
        </GBP>
    </rates>
</exchangerate>

如何删除/跳过费率标签?

最佳答案

我建议您将 XML 构造为:

<exchangerate>
    <date>2015-05-04</date>
    <currency code="EUR">
        <rate code="EUR">1</rate >
        <rate code="GBP">0.73788</rate >
        <rate code="USD">1.1152</rate >
    </currency>
    <currency code="GBP">
        <rate code="EUR">1.35523</rate >
        <rate code="GBP">1</rate >
        <rate code="USD">1.51136</rate >
    </currency>
    <currency code="USD">
        <rate code="EUR">0.8967</rate >
        <rate code="GBP">0.66166</rate >
        <rate code="USD">1</rate >
    </currency>
</exchangerate> 

并且您有多个类(class):

@XmlAccessorType(XmlAccessType.FIELD)
public class ExchangeRates {
    @XmlJavaTypeAdapter(DateAdapter.class)
    private Date date;

    @XmlElement(name="currency")
    private List<Currency> currencies = new ArrayList<>();

    ....
}

@XmlAccessorType(XmlAccessType.FIELD)
public class Currency {
    @XmlAttribute
    private String code;

    @XmlElement(name="rate")
    private List<Rate> rates= new ArrayList<>();

    ....
}


@XmlAccessorType(XmlAccessType.FIELD)
public class Rate {
    @XmlAttribute
    private String code;

    @XmlValue
    private Double value;

    ....
}

关于java - 使用 Jaxb 解码嵌套 Map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45793531/

相关文章:

python - 正则表达式匹配双下划线?

java - UnmarshalException : unexpected element (uri :"http://www.namespace.com/RTS", 本地 :"container")

Java - 验证框架

java - 在 Linux 上使用 Java 对 Active Directory 进行身份验证

java - 将 JPG 文件加载到 Swing 应用程序中

java - Oracle SOA Suite 中的自定义记录器记录到错误的文件

java - Java 中是否有类似于 Python 的 FOR ... IN ... 循环?

python - 使用正则表达式获取 XML 父标签

java - JAXB @XmlSeeAlso 导致与域对象的紧密耦合

java - JAXB XmlID 和 XmlIDREF 注释(架构到 Java)