在相同的情况下,@ XmlJavaTypeAdapter被忽略

时间:2013-10-23 20:52:47

标签: java xml jaxb jaxb2

当调用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);
    } 
}

1 个答案:

答案 0 :(得分:1)

根据JAXB 2.2 specification

  

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

     
      
  1. 其引用类型为boundType
  2. 的属性/字段   
  3. 属性/字段,其中boundType用作参数类型
  4.   

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

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

  

根据类型而非实例定义适配器。在   特别是,适配器的设计使其并非总是可行   仅从实例推断出正确的适配器。

修改 在JAXB类中使用Object并不常见。也许您要存储的对象有一些共同点,因此您可以提取可以使用@XmlJavaTypeAdapter进行注释的接口/基类。如果他们没有任何共同点,那么将它们存储为单独的属性会更好。