簡體   English   中英

如何使用Java泛型指定JAXB元素的名稱?

[英]How do I specify the name of a JAXB element using Java generics?

我遇到一種情況,其中Java對象包含需要將其編組為xml的通用Payload<T> 因此,給出以下類:

AbstractBox

@XmlTransient
public abstract class AbstractBox {
    String type = this.getClass().getSimpleName();
    String name = this.getClass().getCanonicalName();

    // setters/getters snipped

    public abstract String saySomething();
}

小盒子

@XmlRootElement(name="small-box")
@XmlType(name="small-box")
public class SmallBox extends AbstractBox {

    @XmlElement
    public String getMsg() {
        return saySomething();
    }
    public void setMsg(String msg) {
        // do nothing
    }

    @Override
    public String saySomething() {
        return "I'm a small box";
    }
}

有效載荷

@XmlTransient
public class Payload<T> {
    private T payload;

    public T getPayload() {
        return payload;
    }

    public void setPayload(T payload) {
        this.payload = payload;
    }
}

和一些這樣的代碼:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class JaxbAnnotationsTest<P>
{
    String name;
    int age;
    int id;
    Payload<P> payload;

    // setters and getters snipped

    public static void main(String[] args) {
        JaxbAnnotationsTest<AbstractBox> example = new JaxbAnnotationsTest<AbstractBox>();
        example.setName("Brion");
        example.setId(100);
        example.setAge(34);
        Payload<AbstractBox> object = new Payload<AbstractBox>();
        object.setPayload(new SmallBox());
        example.setPayloadContainer(object);

        try {
            XmlMapper xmapper = new XmlMapper();
            xmapper.writeValue(System.out, example);
        } catch (Exception ex) {
            System.err.println("Damn..." + ex.getMessage());
        }
    }

我希望看到:

<JaxbAnnotationsTest>
  <name>Brion</name>
  <age>34</age>
  <id>100</id>
  <payloadContainer>
    <small-box>
      <type>SmallBox</type>
      <name>sandbox.xml.jaxb.annotations.SmallBox</name>
      <msg>I'm a small box</msg>
    </small-box>
  </payloadContainer>
</JaxbAnnotationsTest>

但是我得到了:

<JaxbAnnotationsTest>
  <name>Brion</name>
  <age>34</age>
  <id>100</id>
  <payloadContainer>
    <payload>
      <type>SmallBox</type>
      <name>sandbox.xml.jaxb.annotations.SmallBox</name>
      <msg>I'm a small box</msg>
    </payload>
  </payloadContainer>
</JaxbAnnotationsTest>

我嘗試在具體的子類上使用@XmlTypepayload更改為small-box但這也不起作用。 如果刪除Payload<P>對象並僅具有通用類型P的類成員payload ,則paymentContainer標記將消失,但是payload仍然存在,並且不使用我指定的small-box名稱。

有沒有一種方法可以強制JAXB(任何實現)將標記設置為子類中指定的名稱,而不是通用類型屬性?

更新:選定的答案提供了解決方案,但我也想跟進該問題。 我的問題有兩個:

  1. 我在Payload<T>類上使用@XmlTransient ,並且需要在setPayload(T payload)方法上使用@XmlAnyElement批注(盡管我懷疑只要對setter / getter對的哪個方法都進行了注釋就可以了因為只有一個具有注釋)。
  2. 我用傑克遜2的JacksonJaxbXmlProvider這是一個不完整的JAXB實現這是忽略@XmlRootElement用作的值的元素的@XmlAnyElement -annotated屬性。

更改我的JAXB提供程序以使用Java 6/7內置JAXB提供程序會生成預期的輸出。

您的Payload類希望將任何bean類型都作為屬性,因此JAXB不知道如何編組該特定對象(在本例中為SmallBox )。 由於您需要將通用屬性保留在有效負載中,因此解決方案應為

  1. 刪除@XmlTransient批注以使這些類型可用於編組(我想知道它如何與您提到的此批注一起使用)
  2. 注釋setPayloadPayload@XmlAnyElement如下

公共類有效載荷{私有T有效載荷;

public T getPayload() {
    return payload;
}

@XmlAnyElement
public void setPayload(T payload) {
    this.payload = payload;
}

}

@XmlAnyElement javadoc說

將JavaBean屬性映射到XML信息集表示形式和/或JAXB元素。

這意味着傳遞給setPayload ()的任何已知bean類型(用@XmlRootElement注釋)將由JAXB解析為其對應的類型,這里bean是SmallBox ,否則為默認元素類型(我認為應該是默認元素類型) org.w3c.dom.Element實現)。 進行此更改后,它將很好地將JaxbAnnotationsTest編組為以下xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxbAnnotationsTest>
    <age>34</age>
    <id>100</id>
    <name>Brion</name>
    <payloadContainer>
        <small-box>
            <name>org.mycode.SmallBox</name>
            <type>SmallBox</type>
            <msg>I'm a small box</msg>
        </small-box>
    </payloadContainer>
</jaxbAnnotationsTest>

希望對您有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM