问题描述
我这里有一个情况,试图充当两个 API 之间的网关.我需要做的是:
I have a situation here, trying to act as a gateway between two APIs. What I need to do, is:
- 向 APIa 发出请求;
- 将 XML 响应解析(编组)为 java 对象;
- 对其稍作改动;
- 然后以 XML(解组)形式向另一端 (APIb) 提供响应.
问题是我使用同一个对象来解析 API 响应并将响应发送到另一端.
The thing is that I use the same object to parse the API response and to send the response to the other end.
public class ResponseAPI{
@XmlElement(name="ResponseCode") //I receive <ResponseCode> but I need to send <ResultCode>
private String responseCode;
//getter and setter
}
正如评论所说:我收到但我需要发送
as the comment says: I receive but I need to send
有没有办法在不创建另一个带有 ResultCode 的额外类的情况下完成这项工作?
Is there a way to get this done without having to create another extra class which carries ResultCode?
提前致谢!
推荐答案
注意:
Ilya 给出的答案有效,但不保证适用于所有 JAXB 实现,甚至适用于不同版本的 JAXB单个 JAXB 实现.当决定封送哪个元素取决于值的类型时,@XmlElements
注释很有用(请参阅:http://blog.bdoughan.com/2010/10/jaxb-and-xsd-choice-xmlelements.html).在您的用例中,ResponseCode
和 ResultCode
元素都对应于类型 String
,解组将始终正常工作,但选择要输出的元素是任意的.一些 JAXB Impls 可能有最后指定的胜利,但其他人可能很容易获得第一次胜利.
The answer given by Ilya works but isn't guaranteed to work across all implementations of JAXB or even across versions of a single JAXB implementation. The @XmlElements
annotation is useful when the decision of which element to marshal depends on the type of the value (see: http://blog.bdoughan.com/2010/10/jaxb-and-xsd-choice-xmlelements.html). In your use case both the ResponseCode
and ResultCode
elements correspond to type String
, unmarshalling will always work fine, but the choice of which element to output is arbitrary. Some JAXB Impls may have last specified wins, but others could easily have first wins.
您可以利用 @XmlElementRef
执行以下操作.
You could do the following by leveraging @XmlElementRef
.
响应API
我们将 responseCode
属性从 String
类型更改为 JAXBElement
.JAXBElement
允许我们存储元素名称和值.
We will change the responseCode
property from type String
to JAXBElement<String>
. The JAXBElement
allows us to store the element name as well as the value.
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;
}
}
对象工厂
我们在 ResponseAPI
类上使用的 @XmlElementRef
注释对应于使用 @XmlRegistry<注释的类上的
@XmlElementDecl
注释/代码>.传统上,此类称为 ObjectFactory
,但您可以随意调用它.
The @XmlElementRef
annotations we used on the ResponseAPI
class correspond to @XmlElementDecl
annotations on a class annotated with @XmlRegistry
. Traditionally this class is called ObjectFactory
but you can call it anything you want.
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);
}
}
演示代码
input.xml
<responseAPI>
<ResponseCode>ABC</ResponseCode>
</responseAPI>
演示
在创建 JAXBContext
时,我们需要确保包含包含 @XmlElementDecl
注释的类.
When creating the JAXBContext
we need to ensure that we include the class that contains the @XmlElementDecl
annotations.
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);
}
}
输出
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<responseAPI>
<ResultCode>ABC</ResultCode>
</responseAPI>
这篇关于@XmlElement 具有多个名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!