JAXB:将XML标记放在抽象类上

时间:2014-12-01 19:57:05

标签: java xml inheritance jaxb

我正在使用来自第三方的界面,他们对请求/响应和通知有一种特殊的(至少我的想法)XML格式。 XML需要如下所示:

<Message>
  <Version>3.1</Version>
  <Request>
    <Request_Name>
      <RequestID> Request ID </RequestID>
      ...
    </Request_Name>
  </Request>
</Message>

Request代码也可以是NotificationResponse中的一个。所有Messages只有这三个中的一个。 RequestResponse都有RequestIDResponse也有ReturnValueNotification有一个Session

为了防止重复,我想为这三种类型中的每一种创建一个抽象类,它几乎可以工作!我可以编组和解组的内容如下:

<Message>
  <Version>3.1</Version>
  <Request_Name>
    <RequestID> Request ID </RequestID>
    ...
  </Request_Name>
</Message>

请注意丢失的Request标记! NotificationResponse也是如此。所有信息都在那里,但这些包装标签正在杀了我!

问题: 我可以在抽象类上放置XML标记吗?或者我是否需要将其设为非抽象并创建另一个顶级抽象类作为“真正的”抽象基类?

我对JAXB的经验不多,所以我希望有一种简单的方法可以做到这一点。我尝试将邮件的request字段改为XMLElement,但只会将Request_Name标记更改为Request并添加类型说明。

我的代码基本上如下所示,为简洁起见,我们采用了setter和CTOR。

基础Message类:

@XmlRootElement(name = "Message")
public class Message {
    @XmlElement(required = true, name = "Version") private String version;
    private Request request;
    private Response response;
    private Notification notification;

    @XmlElementRef(required = false)
    public Request getRequest() {
        return request;
    }

    @XmlElementRef(required = false)
    public Response getResponse() {
        return response;
    }

    @XmlElementRef(required = false)
    public Notification getNotification() {
        return notification;
    }
}

摘要Request类。类似于NotificationResponse

@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)
public abstract class Request {
    private String requestId;

    @XmlElement(name = "RequestID", required = true)
    public String getRequestId() {
        return requestId;
    }
}

示例Request实施:

@XmlRootElement(name = "RegForAllNotificationsRequest")
public class RegForAllNotificationsRequest extends Request {
    private long session;
    private boolean register;

    @XmlElement(name = "SessionToUse")
    public long getSession() {
        return session;
    }
    @XmlElement(name = "Register")
    public boolean isRegister() {
        return register;
    }
}

上面的内容被编组了:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Message>
    <Version>8.3</Version>
    <RegForAllNotificationsRequest>
        <RequestID>94668</RequestID>
        <SessionToUse>548248</SessionToUse>
        <Register>true</Register>
    </RegForAllNotificationsRequest>
</Message>

我需要的地方:

<?xml version="1.0" encoding="UTF-8"?>
<Message>
    <Version>8.3</Version>
    <Request>
        <RegForAllNotificationsRequest>
            <RequestID>94668</RequestID>
            <SessionToUse>548248</SessionToUse>
            <Register>true</Register>
        </RegForAllNotificationsRequest>
    </Request>
</Message>

1 个答案:

答案 0 :(得分:1)

此处您需要的是RequestContainer类,其标记名称为请求。该类将包含实际的请求实现。这是必需的,因为JAXB将每个类呈现为单独的标记。标签层次结构不是基于类层次结构构建的。

容器类看起来像这样:

@XmlRootElement(name = "Request")
public class RequestContainer {
   private Request request;
}

同样,对于NotificationResponseMessage类将包含每个容器类的实例,如下所示:

@XmlRootElement(name = "Message")
public class Message {
    @XmlElement(required = true, name = "Version") private String version;
    private RequestContainer request;
    private ResponseContainer response;
    private NotificationContainer notification;

    @XmlElementRef(required = false)
    public Request getRequest() {
        return request;
    }

    @XmlElementRef(required = false)
    public Response getResponse() {
        return response;
    }

    @XmlElementRef(required = false)
    public Notification getNotification() {
        return notification;
    }
}

希望这有帮助。