我正在使用JAXB来编组Java类。我无法弄清楚我必须在以下场景中使用哪个xml注释:
XSD:
...
<xs:complexType name = "Message">
<xs:sequence>
<xs:element name = "memberOne" type = "xs:hexBinary"/>
<xs:element name = "memberTwo" type = "xs:unsignedByte"/>
<xs:choice>
<xs:element name = "typeOne" type = "MessageTypeOne"/>
<xs:element name = "typeTwo" type = "MessageTypeTwo"/>
<xs:element name = "typeThree" type = "MessageTypeThree"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
..
MessageTypeOne/Two/Three
之前已定义,但对此方案并不重要。
Java类:
Message.java
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Message", propOrder = {
"memberOne",
"memberTwo",
})
public class Message{
@XmlElement(required = true, type = String.class)
@XmlJavaTypeAdapter(HexBinaryAdapter.class)
@XmlSchemaType(name = "hexBinary")
protected byte[] memberOne;
@XmlSchemaType(name = "unsignedByte")
protected short memberTwo;
//Which annotations i have to use here?
protected MessageBody messageBody;
...
}
MessageBody.java
//Which annotations i have to use here?
public class MessageBody {
//Which annotations i have to use here?
MessageType myChoice;
...
}
XSD文件中未提及 MessageBody
。编组时必须“忽略”它。只有其类成员myChoice
必须编组。
我已经考虑过实现自己的XmlAdapter
,但找不到解决问题的方法。
MessageType.java
public abstract class MessageType { ... }
那是基类。
MessageTypeOne.java
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "MessageTypeOne", propOrder = {
"memberOne",
"memberTwo",
})
public class MessageTypeOne extends MessageType {
@XmlSchemaType(name = "unsignedByte")
protected short memberOne;
@XmlSchemaType(name = "unsignedByte")
protected short memberTwo;
...
}
MessageTypeTwo/Three
与此类似。
我目前可以实现的XML输出示例:
<Message>
<memberOne>01020304</memberOne>
<memberTwo>5</memberOne>
<MessageBody>
<MessageTypeOne>
...
</MessageTypeOne>
</MessageBody>
</Message>
所需的XML输出:
<Message>
<memberOne>01020304</memberOne>
<memberTwo>5</memberOne>
<MessageTypeOne>
...
</MessageTypeOne>
</Message>
所以我只想删除<MessageBody> .. </MessageBody>
标记。
显然我只想澄清这个问题。实际上代码要复杂得多。
我不允许更改XSD文件,只允许对java类进行微小更改。我无法改变彼此之间的关系。
我的问题:
我必须使用哪些注释来跳过MessageBody
类
编组?我怎么能告诉JAXB只对其成员进行编组
myChoice
多态在JAXB中是如何工作的?我需要使用哪个注释 实现这一目标?
这个问题是否可以用JAXB解决?
编辑:添加了XML示例输出
答案 0 :(得分:1)
多态在JAXB中如何工作?我需要使用哪个注释来实现它?
你可以用。实现这种JAXB多态
@XmlElements
注释:
@XmlAccessorType(XmlAccessType.FIELD)
public class MessageBody {
@XmlElements({
@XmlElement(name = "MessageTypeOne", type = MessageTypeOne.class),
@XmlElement(name = "MessageTypeTwo", type = MessageTypeTwo.class),
@XmlElement(name = "MessageTypeThree", type = MessageTypeThree.class)
})
protected MessageType myChoice;
...
}
我必须使用哪些注释来跳过
MessageBody
类 编组?我怎样才能告诉JAXB只对其成员myChoice
进行编组?
您可以删除MessageBody
课程。
而是将myChoice
属性直接放入Message
类。
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Message", propOrder = {
"memberOne",
"memberTwo",
"myChoice"
})
public class Message{
@XmlElement(required = true, type = String.class)
@XmlJavaTypeAdapter(HexBinaryAdapter.class)
@XmlSchemaType(name = "hexBinary")
protected byte[] memberOne;
@XmlSchemaType(name = "unsignedByte")
protected short memberTwo;
@XmlElements({
@XmlElement(name = "MessageTypeOne", type = MessageTypeOne.class),
@XmlElement(name = "MessageTypeTwo", type = MessageTypeTwo.class),
@XmlElement(name = "MessageTypeThree", type = MessageTypeThree.class)
})
protected MessageType myChoice;
//...
}
答案 1 :(得分:0)
感谢Thomas Fritschs Answer,他提出了基本想法,我能够解决这个问题。我基本上会用他的代码回答我自己的问题。
我通常不得不面对的问题是我不被允许摆脱MessageBody
课程。所以我必须在班级messageBodyChoice
中创建一个成员Message
才能直接访问它。
此时编组工作正常,解组不会。 XSD文件不包含MessageBody
的定义,因此JAXB永远不会自动解组它。
为了手动执行此操作,我添加了以下方法:
void afterUnmarshal(Unmarshaller u, Object parent) { ... }
(观看此帖子了解更多详情:How can I have JAXB call a method after it has completed unmarshalling an XML file into an object?)
您可以简单地将此方法添加到任何未进行任何其他工作的非编组的类中。
使用这种方法,我可以在解组后初始化messageBody
。
代码中的解决方案:
<强> Message.java 强>
@XmlAccessorType(XmlAccessType.NONE)
@XmlType(name = "Message", propOrder = {
"memberOne",
"memberTwo",
"messageBodyChoice"
})
public class Message{
@XmlElement(required = true, type = String.class)
@XmlJavaTypeAdapter(HexBinaryAdapter.class)
@XmlSchemaType(name = "hexBinary")
protected byte[] memberOne;
@XmlSchemaType(name = "unsignedByte")
protected short memberTwo;
protected MessageBody messageBody;
//This member is only needed for marshalling!!!
@XmlElements({
@XmlElement(name = "MessageTypeOne", type = MessageTypeOne.class),
@XmlElement(name = "MessageTypeTwo", type = MessageTypeTwo.class),
@XmlElement(name = "MessageTypeThree", type = MessageTypeThree.class)
})
protected MessageType messageBodyChoice;
//...
/*
* This setter ensures that messageBodyChoice always contains
* the value of messageBody.getChoice()
*/
public void setMessageBody(MessageBody messageBody){
this.messageBody = messageBody;
if(messageBody != null)
this.messageBodyChoice = messageBody.getChoice();
}
//...
void afterUnmarshal(Unmarshaller u, Object parent) {
//at this point messageBody is null
messageBody = new MessageBody();
messageBody.setChoice(messageBodyChoice);
}
}
请注意,我已将@XmlAccessorType
更改为XmlAccessType.NONE
。
有关@XmlAccessorType
here。
这可能看起来不干净,但这是我可以找到的唯一可能的方法来避免XML输出中的<MessageBody>
标记。