1

当调用 JAXB.marshal 时,我正在使用 Class AdapterDataObj 将 Class DataObj 转换为 AdaptedDataObj。


package test;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlJavaTypeAdapter(AdapterDataObj.class)
public class DataObj { 
    public String bla = "I'm DataObj";
    public String name; 
    public DataObj(String name) { 
        this.name = name;
    }

    } 
    

package test; 
public class AdaptedDataObj {
        public String bla="I'm AdaptedDataObj";
        public  String name;

        public AdaptedDataObj(String name) {
            this.name = name;
        }
}

package test; 
import javax.xml.bind.annotation.adapters.XmlAdapter; 
public class AdapterDataObj extends XmlAdapter { 
    @Override
    public DataObj unmarshal(AdaptedDataObj v) throws Exception {
        return null; // not needed in this case
    }

    @Override
    public AdaptedDataObj marshal(DataObj v) throws Exception {
        System.out.println("Marschal for " + v.name + " called!");
        return new AdaptedDataObj(v.name);
    } 
}

现在我将 DataObj 放入一个新的类中,并为这个类调用 JAXB.marshal。输出看起来不错。我还收到调用 AdaptedDataObj 的消息。


package test; 
import javax.xml.bind.JAXB; 
public class Testobj { 
    public DataObj x; 
    public Testobj() {
        x = new DataObj("Hallo World");
    }

    public static void main(String[] args) throws Exception {
        System.out.println("Testobj");
        System.out.println("=================================");
        Testobj to = new Testobj();
        JAXB.marshal(to, System.out);
    } 
}

现在我将“ public DataObj x;”更改为“ public Object x;”,因为我不仅想在该类中存储 DataObj。

但在这种情况下,不再调用 AdapterDataObj。DataObj 而不是 AdapterDataObj 导出为 xml。

知道问题出在哪里吗?

我还尝试将@XmlJavaTypeAdapter 添加到package-info.java 中但没有成功。AdapterDataObj 仍然没有被调用。我已经用 Java 1.7.0_45 和 1.8.0-ea 进行了测试。


package test; 
import javax.xml.bind.JAXB;
import javax.xml.bind.annotation.XmlSeeAlso; 
@XmlSeeAlso({DataObj.class})
public class Testobj3 { 
        public Object x; 
    public Testobj3() {
        x = new DataObj("Hallo World");
    }

    public static void main(String[] args) throws Exception {
        System.out.println("Testobj3");
        System.out.println("=================================");
        Testobj3 to3 = new Testobj3();
        JAXB.marshal(to3, System.out);
    } 
}
4

1 回答 1

2

根据JAXB 2.2 规范

扩展 XmlAdapter 并在类、接口或 Enum 类型上指定的 @XmlJavaTypeAdapter(即在与元注释 @Target={type} 匹配的程序元素上)必须在引用点适应 boundType,如下所示:

  1. 引用类型为 boundType 的属性/字段
  2. boundType 用作参数类型的属性/字段

因此,字段/属性必须是给定类型,以便 JAXB 识别需要使用适配器。

出于同样的原因,您不能在根元素上使用适配器。可以在已关闭的 JAXB 问题JAXB-117中找到解释:

适配器是针对类型而不是实例定义的。特别是,适配器的设计方式并不总是可以仅从实例中推断出正确的适配器。

编辑 在 JAXB 类中使用 Object 不是很常见。也许您要存储的对象有一些共同点,以便您可以提取可以用@XmlJavaTypeAdapter. 如果它们没有任何共同点,最好将它们存储为单独的属性。

于 2013-10-24T08:59:56.873 回答