我正在使用JAXB的EclipseLink实现(2.3)将POJO映射到XML并遇到以下用例的问题:
public abstract class A {
public abstract Set<X> getX();
// There is no setter
}
public class B extends A {
// Set via constructor
private Set<X> x;
@Override
public Set<X> getX();
}
我在外部绑定文件中完全定义了映射本身,我将类A设置为瞬态,如下所示:
<java-type name="foo.A" xml-transient="true"/>
和B组:
<java-type name="bar.B" xml-accessor-type="PROPERTY">
<xml-root-element name="B" />
<java-attributes>
<xml-element java-attribute="x" xml-path="..."/>
</java-attributes>
</java-type>
现在,在编组时我得到了异常:“在类[bar.B]上找到名为[x]的重复属性” 在我看来,它来自A中的抽象声明,由B继承。
将B的访问者类型设置为FIELD,摆脱了这个错误,遗憾的是这不是一个选项,因为我在B中有一个额外的属性来编组,它不会返回一个字段而是一个计算值,所以我是坚持使用PROPERTY(以下工作:将B的访问器类型设置为FIELD并使用@XmlPath注释映射额外属性 - 但我不希望在我的代码中添加注释。)
对于B级,我遇到了存取器类型的PROPERTY,我的下一次尝试是:
<java-type name="foo.A" xml-accessor-type="NONE"/>
防止抽象属性被B继承,这让我得到了:
Ignoring attribute [x] on class [bar.B] as no Property was generated for it.
使用此映射也发生了同样的情况:
<java-type name="foo.A" xml-accessor-type="PROPERTY">
<java-attributes>
<xml-transient java-attribute="x"/>
</java-attributes>
</java-type>
在这两种情况下都会忽略属性“x”。
我现在花了很多时间在这上面 - 我无法想象它不可能让它发挥作用吗?
我现在的解决方法:
让foo.A成为瞬态,为bar.B指定访问器类型FIELD(它使我的属性'x'没有问题)并使用代码中的注释映射B中的额外属性。 但如前所述:我想在没有注释的情况下彻底解决这个问题 - 任何人都有任何想法?布莱斯? :)
的问候,
- 曲
答案 0 :(得分:1)
注意:我是EclipseLink JAXB (MOXy)主管,是JAXB 2 (JSR-222)专家组的成员。
您似乎遇到了错误。您可以通过以下链接跟踪我们在此问题上的进展。我在下面提供了有关此问题的其他详细信息:
使用注释
如果您要使用JAXB / MOXy注释来映射此用例,您可以在@XmlAccessorType(XmlAccessType.NONE)
类上设置A
并执行以下操作:
的 A 强> 的
package forum8727402;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.NONE)
public abstract class A {
public abstract String getX();
}
的乙强> 的
package forum8727402;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlRootElement
public class B extends A {
@XmlPath("a/b/c/text()")
private String x;
public B() {
x = "Hello World";
}
@Override
public String getX() {
return x;
}
@XmlElement
public String getCalculatedValue() {
return "Calculated Value";
}
}
的演示强> 的
package forum8727402;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(B.class);
B b = new B();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(b, System.out);
}
}
的输出强> 的
<?xml version="1.0" encoding="UTF-8"?>
<b>
<a>
<b>
<c>Hello World</c>
</b>
</a>
<calculatedValue>Calculated Value</calculatedValue>
</b>
使用MOXy的外部映射文件
的 oxm.xml 强> 的
下面是一个MOXy external mapping file,它代表了之前显示的注释的等价物:
<?xml version="1.0" encoding="UTF-8"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="forum8727402">
<java-types>
<java-type name="A" xml-accessor-type="NONE"/>
<java-type name="B">
<xml-root-element/>
<java-attributes>
<xml-element java-attribute="x" xml-path="a/b/c/text()"/>
<xml-element java-attribute="calculatedValue"/>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
的演示强> 的
下面的代码演示了如何引用映射文件:
package forum8727402;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
public class Demo {
public static void main(String[] args) throws Exception {
Map<String, Object> properties = new HashMap<String, Object>(1);
properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum8727402/oxm.xml");
JAXBContext jc = JAXBContext.newInstance(new Class[] {A.class, B.class}, properties);
B b = new B();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(b, System.out);
}
}
的输出强> 的
[EL Warning]: 2012-01-04 14:45:46.366--Ignoring attribute [x] on class [forum8727402.xml.B] as no Property was generated for it.
<?xml version="1.0" encoding="UTF-8"?>
<b>
<calculatedValue>Calculated Value</calculatedValue>
</b>