Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JAXB2.x:如何从父类重写XmlElement注释-任务不可能?_Java_Inheritance_Jaxb_Marshalling_Jaxb2 - Fatal编程技术网

Java JAXB2.x:如何从父类重写XmlElement注释-任务不可能?

Java JAXB2.x:如何从父类重写XmlElement注释-任务不可能?,java,inheritance,jaxb,marshalling,jaxb2,Java,Inheritance,Jaxb,Marshalling,Jaxb2,为什么这是不可能的?它看起来很简单,但它的行为并不像预期的那样 摘要:类A使用聚合的DataA bean,而类B(类A的子类)使用聚合的DataB bean(而DataB扩展了DataA) 我编写这些测试类是为了可视化和解释我的问题: A类: package test; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xm

为什么这是不可能的?它看起来很简单,但它的行为并不像预期的那样

摘要:类A使用聚合的DataA bean,而类B(类A的子类)使用聚合的DataB bean(而DataB扩展了DataA)

我编写这些测试类是为了可视化和解释我的问题:

A类:

package test;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name="root")
public class A {

  private DataA source = new DataA();

  @XmlElement(name="source")
  public DataA getSource() {
    return source;
  }

  public void setSource(DataA source) {
    this.source = source;
  }

}
以及它的DataA类(我使用了字段注释以便对所有字段进行封送):

现在是类B(类A的子类):我的目标是重用A的功能,并通过使用DataB bean重用DataA bean中的属性:

package test;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name="root")
public class B extends A {

  private DataB source = new DataB();

  public DataB getSource() {
    return this.source;
  }

  public void setSource(DataB source) {
    this.source = source;
  }

}
其对应的数据bean如下所示:

package test;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;

@XmlAccessorType(XmlAccessType.FIELD)
public class DataB extends DataA {
    public String string3 = "3";
}
@XmlElement
public DataB getSource() {
    return this.source;
}
现在,当我整理一个类A的实例时,它给出以下输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
  <source>
    <string1>1</string1>
    <string2>2</string2>
  </source>
</root>
。。。然后该属性被封送两次,因为它一次由父类和子类进行注释。这也是我不想要的:

现在的输出是:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <source xsi:type="dataB" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <string1>1</string1>
        <string2>2</string2>
        <string3>3</string3>
    </source>
    <source>
        <string1>1</string1>
        <string2>2</string2>
        <string3>3</string3>
    </source>
</root>

1.
2.
3.
1.
2.
3.
因此,我对JAXB的期望是以下XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <source>
        <string1>1</string1>
        <string2>2</string2>
        <string3>3</string3>
    </source>
</root>

1.
2.
3.
有没有关于如何调整JAXB以产生预期结果的提示??
感谢您的反馈。

不要在类B上注释源属性。源属性已映射到父类,不应再次映射到子类。由于您正在注释get/set方法,因此将在类B上调用相应的get/set

package test;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name="root")
public class B extends A {

  private StringBuffer source = null;

  public String getSource() {
    return source.toString();
  }

  public void setSource(String source) {
    this.source = new StringBuffer(source);
  }
}
更新

(参考实现)中可能存在错误。使用运行此更新的示例时,我得到以下输出:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <source>
      <string1>1</string1>
      <string2>2</string2>
   </source>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="b">
   <source xsi:type="dataB">
      <string1>1</string1>
      <string2>2</string2>
      <string3>3</string3>
   </source>
</root>
要使用MOXy作为JAXB实现,您需要在模型包(test)中提供一个名为JAXB.properties的文件,其中包含以下条目:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

非常感谢Blaise提供的所有提示。MOXy现在可以很好地使用我的真实应用程序和真实的bean。很好

我目前唯一的缺点是,此配置代码中的最后一行不再工作,因为MOXy当然使用了另一种名称空间前缀映射机制

你有这个的指针吗?我搜索了MOXy文档并搜索了名称空间,但没有找到类似的内容

    NamespacePrefixMapper mapper = new PreferredMapper();
    Marshaller m = context.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
    m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
    m.setProperty("com.sun.xml.internal.bind.namespacePrefixMapper", mapper);

    public static class PreferredMapper extends NamespacePrefixMapper {
      @Override
      public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
        return "z";
    }
}

你不需要用莫西。。 只需更改类B并使用@xml即可

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "root")
public class B extends A {
}


@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({ DataA.class, DataB.class })
@XmlRootElement(name = "source")
@XmlType(name = "source")

public class DataA {
   private String string1 = "1";
   private String string2 = "2";
.....//getters and setters here
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "source")
public class DataB extends DataA {
    private String string3 = "3";
.....//getters and setters here
}

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlSeeAlso({ A.class, B.class }) 
@XmlRootElement(name = "root") 

public class A {

    private DataA source = new DataA();

    public DataA getSource() {
        return source;
    }

    public void setSource(DataA source) {
        this.source = source;
    }

}


 B b = new B();
        DataB db = new DataB();
        db.setString1("1");
        db.setString2("2");
        db.setString3("3");
        b.setSource(db);
        marshaller.marshal(b, System.out);
最后将写:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <source>
        <string1>1</string1>
        <string2>2</string2>
    </source>
</root>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <source xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="dataB">
        <string1>1</string1>
        <string2>2</string2>
        <string3>3</string3>
    </source>
</root>

1.
2.
1.
2.
3.

您可以使用以下方法:

public interface Data {}

@XmlTransient
public abstract class A {
       private Data data;

       public Data getData(){
              return data;
       }

       public void setData(Data data){
              this.data = data;
       }
}

@XmlAccessorType(XmlAccessType.NONE)
public class ClassA extends A {

       // DataA implements Data
       @XmlElement(type=DataA.class)
       public Data getData(){
              return super.getData();
       }

       public void setData(DataA data){
              super.setData(data);
       }
}

@XmlAccessorType(XmlAccessType.NONE)
public class ClassB extends A {
       // DataB implements Data
       private DataB data;

       @XmlElement(type=DataB.class)
       public DataA getData(){
              return data;
       }

       public void setData(DataB data){
              this.data = data;
       }
}

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement
public class ClassC {
       @XmlElement
       private ClassA classA;
       @XmlElement
       private ClassB classB;

       public ClassA getClassA() {
              return classA;
       }

       public void setClassA(ClassA classA) {
              this.classA = classA;
       }

       public ClassB getClassB() {
              return classB;
       }

       public ClassB setClassB(ClassB classB) {
              this.classB = classB;
       }
}

这个映射对我很有效。

试着将
@xmlement
放在字段上而不是公共方法上是没有帮助的。我还尝试了在字段上不带任何XmlElement注释的XmlAccessType.FIELD,以及在GETTER上不带任何XmlElement注释的XmlAccessType.PROPERTY。。。这是虫子吗?就像这样,它不是真的有用。。。。如您所见,我将注释@xmlacessortype(xmlacesstype.NONE)放在这两个类中。。。因此,只有那些被XmlElement注释的元素得到了封送处理这在JRE主干中得到了修复:+1很高兴见到你:),1 Q。在基类中,它是私有的,那么它又如何进入子类呢?这是不是因为二传接球被压倒了?这太棒了,真的很有帮助@Oracle(Sun)的bzero-JavaSE6将包含JAXB参考实现Metro。我是MOXy技术负责人。您可以将MOXy与以下配置一起使用:1)eclipselink.jar 2)bundle:org.eclipse.persistence.asm、org.eclipse.persistence.core和org.eclipse.persistence.MOXy。@bzero-就JAXB而言,该属性属于DataA类型,因为这是超类上的属性类型。当数据的实例被封送时,xsi:type属性用于将其限定为子类型的实例。签出:行不使用MOXy:m.setProperty(“com.sun.xml.internal.bind.namespacePrefixMapper”,mapper);MOXy不支持namespacePrefixMapper,但是在MOXy中可以更轻松地实现这一点。MOXy将使用@XmlSchema注释中指定的前缀。有关示例,请参见:太棒了,谢谢!现在它完全可以正常工作了,就像它在一天前应该可以正常工作一样。嗨,这是一个有趣的方法,但是你有没有搞错什么?因为有类A和“B扩展了A”,所以A对B一无所知。在类A中应用实际引用类B的注释打破了面向对象的数据建模?也许你可以把@也应用到B类?那就可以了,我会试试看。
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "root")
public class B extends A {
}


@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({ DataA.class, DataB.class })
@XmlRootElement(name = "source")
@XmlType(name = "source")

public class DataA {
   private String string1 = "1";
   private String string2 = "2";
.....//getters and setters here
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "source")
public class DataB extends DataA {
    private String string3 = "3";
.....//getters and setters here
}

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlSeeAlso({ A.class, B.class }) 
@XmlRootElement(name = "root") 

public class A {

    private DataA source = new DataA();

    public DataA getSource() {
        return source;
    }

    public void setSource(DataA source) {
        this.source = source;
    }

}


 B b = new B();
        DataB db = new DataB();
        db.setString1("1");
        db.setString2("2");
        db.setString3("3");
        b.setSource(db);
        marshaller.marshal(b, System.out);
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <source>
        <string1>1</string1>
        <string2>2</string2>
    </source>
</root>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <source xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="dataB">
        <string1>1</string1>
        <string2>2</string2>
        <string3>3</string3>
    </source>
</root>
public interface Data {}

@XmlTransient
public abstract class A {
       private Data data;

       public Data getData(){
              return data;
       }

       public void setData(Data data){
              this.data = data;
       }
}

@XmlAccessorType(XmlAccessType.NONE)
public class ClassA extends A {

       // DataA implements Data
       @XmlElement(type=DataA.class)
       public Data getData(){
              return super.getData();
       }

       public void setData(DataA data){
              super.setData(data);
       }
}

@XmlAccessorType(XmlAccessType.NONE)
public class ClassB extends A {
       // DataB implements Data
       private DataB data;

       @XmlElement(type=DataB.class)
       public DataA getData(){
              return data;
       }

       public void setData(DataB data){
              this.data = data;
       }
}

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement
public class ClassC {
       @XmlElement
       private ClassA classA;
       @XmlElement
       private ClassB classB;

       public ClassA getClassA() {
              return classA;
       }

       public void setClassA(ClassA classA) {
              this.classA = classA;
       }

       public ClassB getClassB() {
              return classB;
       }

       public ClassB setClassB(ClassB classB) {
              this.classB = classB;
       }
}