具有多个名称的@XmlElement

McC*_*Coy 1 java xml jaxb xml-parsing

我这里有一个情况,试图充当两个 API 之间的网关。我需要做的是:

  1. 向 APIa 发出请求;
  2. 将 XML 响应解析(编组)为一个 java 对象;
  3. 对其做些小改动;
  4. 然后以 XML(解组)形式向另一端 (APIb) 提供响应。

问题是我使用相同的对象来解析 API 响应并将响应发送到另一端。

public class ResponseAPI{

@XmlElement(name="ResponseCode") //I receive <ResponseCode> but I need to send <ResultCode>
private String responseCode;

//getter and setter
}
Run Code Online (Sandbox Code Playgroud)

正如评论所说:我收到但我需要发送

有没有办法在不必创建另一个带有 ResultCode 的额外类的情况下完成这项工作?

提前致谢!

Ily*_*lya 5

您可以使用@XmlElements annotaion尝试下一个解决方案

@XmlAccessorType(XmlAccessType.FIELD)
public class ResponseAPI 
{
   @XmlElements(
      {
         @XmlElement(name = "ResponseCode"),
         @XmlElement(name = "ResultCode")
      })
   private String responseCode;
   // ...
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,ResponseCodeResultCode将在解组(xml -> 对象)ResultCode期间和仅在编组(对象 - > xml)期间使用。

所以你可以像解组 XML

<responseAPI>
    <ResponseCode>404</ResponseCode>
</responseAPI>  
Run Code Online (Sandbox Code Playgroud)

编组对象后看起来像

<responseAPI>
    <ResultCode>404</ResultCode>
</responseAPI>
Run Code Online (Sandbox Code Playgroud)


bdo*_*han 5

笔记:

Ilya 给出的答案有效,但不能保证适用于 JAXB 的所有实现,甚至跨单个 JAXB 实现的版本。@XmlElements当决定封送哪个元素取决于值的类型时, 该注释很有用(请参阅:http: //blog.bdoughan.com/2010/10/jaxb-and-xsd-choice-xmlelements.html)。在您的用例中,ResponseCodeResultCode元素都对应于 type String,解组始终可以正常工作,但选择输出哪个元素是任意的。一些 JAXB Impl 可能具有最后指定的胜利,但其他 JAXB Impl 可能很容易获得首次胜利。


您可以利用@XmlElementRef.

Java模型

响应API

我们将responseCode属性从 type更改StringJAXBElement<String>. 允许JAXBElement我们存储元素名称和值。

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class ResponseAPI{

    @XmlElementRefs({
        @XmlElementRef(name = "ResponseCode"),
        @XmlElementRef(name = "ResultCode")
    })
    private JAXBElement<String> responseCode;

    public JAXBElement<String> getResponseCode() {
        return responseCode;
    }

    public void setResponseCode(JAXBElement<String> responseCode) {
        this.responseCode = responseCode;
    }

}
Run Code Online (Sandbox Code Playgroud)

对象工厂

@XmlElementRef我们在类上使用的注释对应ResponseAPI@XmlElementDecl用 注释的类上的注释@XmlRegistry。传统上该类的名称是这样的ObjectFactory,但您可以将其命名为任何您想要的名称。

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;

@XmlRegistry
public class ObjectFactory {

    @XmlElementDecl(name="ResponseCode")
    public JAXBElement<String> createResponseCode(String string) {
        return new JAXBElement<String>(new QName("ResponseCode"), String.class, string);
    }

    @XmlElementDecl(name="ResultCode")
    public JAXBElement<String> createResultCode(String string) {
        return new JAXBElement<String>(new QName("ResultCode"), String.class, string);
    }

}
Run Code Online (Sandbox Code Playgroud)

演示代码

输入.xml

<responseAPI>
    <ResponseCode>ABC</ResponseCode>
</responseAPI>
Run Code Online (Sandbox Code Playgroud)

演示

创建时,JAXBContext我们需要确保包含包含注释的类@XmlElementDecl

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(ResponseAPI.class, ObjectFactory.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("Scratch/src2/forum24554789/input.xml");
        ResponseAPI responseAPI = (ResponseAPI) unmarshaller.unmarshal(xml);

        ObjectFactory objectFactory = new ObjectFactory();
        String responseCode = responseAPI.getResponseCode().getValue();
        JAXBElement<String> resultCodeJAXBElement = objectFactory.createResultCode(responseCode);
        responseAPI.setResponseCode(resultCodeJAXBElement);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(responseAPI, System.out);
    }

}
Run Code Online (Sandbox Code Playgroud)

输出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<responseAPI>
    <ResultCode>ABC</ResultCode>
</responseAPI>
Run Code Online (Sandbox Code Playgroud)