如何使用 jaxb 从两个相似的 xml 文档生成一个对象
How to generate one objects from two similar xml documents with jaxb
我正在尝试与 xml 中的某些提供程序 REST API 集成。我有两个请求和两个非常相似的响应:Operation 响应和 Check响应。
运算:
<Response>
<ReturnCode>0</ReturnCode>
<ReturnMessage>OK</ReturnMessage>
<Commands>
<OperationResponseCommand>
<ResultCode>412</ResultCode>
<ResultMessage>Some message hear</ResultMessage>
<OperationId>125206188472552900</OperationId>
<Id>14507921</Id>
</OperationResponseCommand>
</Commands>
</Response>
检查:
<Response>
<ReturnCode>0</ReturnCode>
<ReturnMessage>OK</ReturnMessage>
<Commands>
<CheckResponseCommand>
<ResultCode>412</ResultCode>
<ResultMessage>Some message hear</ResultMessage>
<OperationId>125206188472552900</OperationId>
</CheckResponseCommand>
</Commands>
</Response>
如您所见,不同之处在于:
<OperationResponseCommand>
而不是 <CheckResponseCommand>
在第一个 xml.
- 里面还有一个标签
<Id>
<OperationResponseCommand>
.
我有两个 class 用于 Response 和 Command.
第一个:
@Data
@XmlRootElement(name = "Response")
@XmlAccessorType(XmlAccessType.FIELD)
public class Response {
@XmlElement(name = "ReturnCode")
private Integer returnCode;
@XmlElement(name = "ReturnMessage")
private String returnMessage;
@XmlElementWrapper(name = "Commands")
@XmlElement(name = "OperationResponseCommand")
private List<Command> commands = new ArrayList<>();
}
第二个:
@Data
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Command {
@XmlElement(name = "ResultCode")
private Integer resultCode;
@XmlElement(name = "ResultMessage")
private String resultMessage;
@XmlElement(name = "OperationId")
private String operationId;
@XmlElement(name = "Id")
private Integer id;
}
为了从 xml 构建响应对象,我正在使用这个 class:
public class JAXBOperations {
public <T> T buildObjectFromXml(Class<T> clazz, String xml) {
try {
StringReader reader = new StringReader(xml);
Unmarshaller unmarshaller = createUnmarshaller(clazz);
return (T) unmarshaller.unmarshal(reader);
} catch (JAXBException e) {
throw new RuntimeException("Exception has been occurred while creating unmarshaller to parse xml to object");
}
}
public <T> String buildXmlFromObject(T objectToXml) {
try {
StringWriter writer = new StringWriter();
Marshaller marshaller = createMarshaller(objectToXml.getClass());
marshaller.marshal(objectToXml, writer);
return writer.toString();
} catch (JAXBException e) {
throw new RuntimeException("Exception has been occurred while creating marshaller to parse object to xml");
}
}
private <T> Marshaller createMarshaller(Class<T> clazz) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
return jaxbContext.createMarshaller();
}
private <T> Unmarshaller createUnmarshaller(Class<T> clazz) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
return jaxbContext.createUnmarshaller();
}
}
方法buildObjectFromXml。它适用于第一个 xml 响应。我有一个这样的对象:
Response(
returnCode=0, returnMessage=OK,
commands=[Command(
resultCode=417,
resultMessage=Processing,
operationId=b6619f26-8583-4272-b89d-d1b200109d06,
id=157427079)])
但是对于第二个 xml 响应,它不起作用。我有:
Response(
returnCode=0,
returnMessage=OK,
commands=[])
我试图更改我的响应 class 的代码。像这样:
@Data
@XmlRootElement(name = "Response")
@XmlAccessorType(XmlAccessType.FIELD)
public class tResponse {
@XmlElement(name = "ReturnCode")
private Integer returnCode;
@XmlElement(name = "ReturnMessage")
private String returnMessage;
@XmlElementWrapper(name = "Commands")
@XmlElementRefs({
@XmlElementRef(name = "OperationResponseCommand", type = Command.class),
@XmlElementRef(name = "CheckResponseCommand", type = Command.class)})
private List<Command> commands = new ArrayList<>();
}
或者这样:
@Data
@XmlRootElement(name = "Response")
@XmlAccessorType(XmlAccessType.FIELD)
public class Response {
@XmlElement(name = "ReturnCode")
private Integer returnCode;
@XmlElement(name = "ReturnMessage")
private String returnMessage;
@XmlElementWrapper(name = "Commands")
@XmlElement(name = "OperationResponseCommand")
private List<Command> operstionCommands = new ArrayList<>();
@XmlElementWrapper(name = "Commands")
@XmlElement(name = "CheckResponseCommand")
private List<Command> checkCommands = new ArrayList<>()
}
但这两个都不行。
我的问题是:我做错了什么?如何更改我的两个 class 的代码以正确转换为对象两种类型的 xml 响应?
代表XML个元素<OperationResponseCommand>
并且 <CheckResponseCommand>
您将需要单独的 classes
这应该是您的 Command
classes 的子 classes。
我们称它们为 OperationResponseCommand
和 CheckResponseCommand
.
所有命令共有的属性应保留在您的
Command
class。将此 class 声明为抽象也是一个好主意。
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public abstract class Command {
@XmlElement(name = "ResultCode")
private Integer resultCode;
@XmlElement(name = "ResultMessage")
private String resultMessage;
@XmlElement(name = "OperationId")
private Integer operationId;
}
命令的特定属性应进入子classes:
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class OperationResponseCommand extends Command {
@XmlElement(name = "Id")
private Integer id;
}
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class CheckResponseCommand extends Command {
}
最后,在你的 Response
class 你需要增强注释
您的 List<Command> commands
属性,因此 JAXB
将知道需要实例化哪个对象 class
在命令的 XML 元素名称上。
(另见 javadoc of @XmlElements
。)
@XmlElementWrapper(name = "Commands")
@XmlElements({
@XmlElement(name = "OperationResponseCommand", type = OperationResponseCommand.class),
@XmlElement(name = "CheckResponseCommand", type = CheckResponseCommand.class)
})
private List<Command> commands = new ArrayList<>();
我正在尝试与 xml 中的某些提供程序 REST API 集成。我有两个请求和两个非常相似的响应:Operation 响应和 Check响应。
运算:
<Response>
<ReturnCode>0</ReturnCode>
<ReturnMessage>OK</ReturnMessage>
<Commands>
<OperationResponseCommand>
<ResultCode>412</ResultCode>
<ResultMessage>Some message hear</ResultMessage>
<OperationId>125206188472552900</OperationId>
<Id>14507921</Id>
</OperationResponseCommand>
</Commands>
</Response>
检查:
<Response>
<ReturnCode>0</ReturnCode>
<ReturnMessage>OK</ReturnMessage>
<Commands>
<CheckResponseCommand>
<ResultCode>412</ResultCode>
<ResultMessage>Some message hear</ResultMessage>
<OperationId>125206188472552900</OperationId>
</CheckResponseCommand>
</Commands>
</Response>
如您所见,不同之处在于:
<OperationResponseCommand>
而不是<CheckResponseCommand>
在第一个 xml.- 里面还有一个标签
<Id>
<OperationResponseCommand>
.
我有两个 class 用于 Response 和 Command.
第一个:
@Data
@XmlRootElement(name = "Response")
@XmlAccessorType(XmlAccessType.FIELD)
public class Response {
@XmlElement(name = "ReturnCode")
private Integer returnCode;
@XmlElement(name = "ReturnMessage")
private String returnMessage;
@XmlElementWrapper(name = "Commands")
@XmlElement(name = "OperationResponseCommand")
private List<Command> commands = new ArrayList<>();
}
第二个:
@Data
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Command {
@XmlElement(name = "ResultCode")
private Integer resultCode;
@XmlElement(name = "ResultMessage")
private String resultMessage;
@XmlElement(name = "OperationId")
private String operationId;
@XmlElement(name = "Id")
private Integer id;
}
为了从 xml 构建响应对象,我正在使用这个 class:
public class JAXBOperations {
public <T> T buildObjectFromXml(Class<T> clazz, String xml) {
try {
StringReader reader = new StringReader(xml);
Unmarshaller unmarshaller = createUnmarshaller(clazz);
return (T) unmarshaller.unmarshal(reader);
} catch (JAXBException e) {
throw new RuntimeException("Exception has been occurred while creating unmarshaller to parse xml to object");
}
}
public <T> String buildXmlFromObject(T objectToXml) {
try {
StringWriter writer = new StringWriter();
Marshaller marshaller = createMarshaller(objectToXml.getClass());
marshaller.marshal(objectToXml, writer);
return writer.toString();
} catch (JAXBException e) {
throw new RuntimeException("Exception has been occurred while creating marshaller to parse object to xml");
}
}
private <T> Marshaller createMarshaller(Class<T> clazz) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
return jaxbContext.createMarshaller();
}
private <T> Unmarshaller createUnmarshaller(Class<T> clazz) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
return jaxbContext.createUnmarshaller();
}
}
方法buildObjectFromXml。它适用于第一个 xml 响应。我有一个这样的对象:
Response(
returnCode=0, returnMessage=OK,
commands=[Command(
resultCode=417,
resultMessage=Processing,
operationId=b6619f26-8583-4272-b89d-d1b200109d06,
id=157427079)])
但是对于第二个 xml 响应,它不起作用。我有:
Response(
returnCode=0,
returnMessage=OK,
commands=[])
我试图更改我的响应 class 的代码。像这样:
@Data
@XmlRootElement(name = "Response")
@XmlAccessorType(XmlAccessType.FIELD)
public class tResponse {
@XmlElement(name = "ReturnCode")
private Integer returnCode;
@XmlElement(name = "ReturnMessage")
private String returnMessage;
@XmlElementWrapper(name = "Commands")
@XmlElementRefs({
@XmlElementRef(name = "OperationResponseCommand", type = Command.class),
@XmlElementRef(name = "CheckResponseCommand", type = Command.class)})
private List<Command> commands = new ArrayList<>();
}
或者这样:
@Data
@XmlRootElement(name = "Response")
@XmlAccessorType(XmlAccessType.FIELD)
public class Response {
@XmlElement(name = "ReturnCode")
private Integer returnCode;
@XmlElement(name = "ReturnMessage")
private String returnMessage;
@XmlElementWrapper(name = "Commands")
@XmlElement(name = "OperationResponseCommand")
private List<Command> operstionCommands = new ArrayList<>();
@XmlElementWrapper(name = "Commands")
@XmlElement(name = "CheckResponseCommand")
private List<Command> checkCommands = new ArrayList<>()
}
但这两个都不行。
我的问题是:我做错了什么?如何更改我的两个 class 的代码以正确转换为对象两种类型的 xml 响应?
代表XML个元素<OperationResponseCommand>
并且 <CheckResponseCommand>
您将需要单独的 classes
这应该是您的 Command
classes 的子 classes。
我们称它们为 OperationResponseCommand
和 CheckResponseCommand
.
所有命令共有的属性应保留在您的
Command
class。将此 class 声明为抽象也是一个好主意。
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public abstract class Command {
@XmlElement(name = "ResultCode")
private Integer resultCode;
@XmlElement(name = "ResultMessage")
private String resultMessage;
@XmlElement(name = "OperationId")
private Integer operationId;
}
命令的特定属性应进入子classes:
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class OperationResponseCommand extends Command {
@XmlElement(name = "Id")
private Integer id;
}
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class CheckResponseCommand extends Command {
}
最后,在你的 Response
class 你需要增强注释
您的 List<Command> commands
属性,因此 JAXB
将知道需要实例化哪个对象 class
在命令的 XML 元素名称上。
(另见 javadoc of @XmlElements
。)
@XmlElementWrapper(name = "Commands")
@XmlElements({
@XmlElement(name = "OperationResponseCommand", type = OperationResponseCommand.class),
@XmlElement(name = "CheckResponseCommand", type = CheckResponseCommand.class)
})
private List<Command> commands = new ArrayList<>();