在不可修改的域Java类中重写JAXB绑定

时间:2021-10-26 17:01:53

I have spent the whole day trying to figure out this problem (including extensive searching on this site), but I can't find an answer to my problem. I am trying to achieve this:

我花了一整天的时间试图解决这个问题(包括在这个网站上广泛搜索),但是我找不到问题的答案。我正在努力实现这一点:

  • Convert between XML and some existing Java objects that I have no control over
  • 在XML和一些我无法控制的现有Java对象之间进行转换
  • Names of elements in the resulting/source XML differ from names of properties of the Java classes
  • 结果/源XML中的元素名称与Java类的属性名称不同
  • I am limited to jaxb-2.0
  • 我仅限于jaxb-2.0。
  • I may introduce a wrapping class that can contain the annotations
  • 我可能会介绍一个包装类,它可以包含注释

Let me show you an example of what I'm trying to achieve. Let's assume that the Java class I have no control over looks like this:

让我给你们举个例子来说明我想要达到的目标。假设我无法控制的Java类如下:

public class TopNoControlClass {

    private BottomNoControlClass bottomNoControlObject;

    public TopNoControlClass(BottomNoControlClass bottomNoControlObject) {
        super();
        this.bottomNoControlObject = bottomNoControlObject;
    }

    public BottomNoControlClass getBottomNoControlObject() {
        return bottomNoControlObject;
    }
    public void setBottomNoControlObject(BottomNoControlClass bottomNoControlObject) {
        this.bottomNoControlObject = bottomNoControlObject;
    }
}

And the referenced class:

和引用的类:

public class BottomNoControlClass {

    private String foo;

    public BottomNoControlClass(String foo) {
        super();
        this.foo = foo;
    }

    public String getFoo() {
        return foo;
    }
    public void setFoo(String foo) {
        this.foo = foo;
    }
}

And imagine I want to get this out of the marshalling:

想象一下我想从编组中得到这个

<?xml version="1.0" encoding="UTF-8"?>
<Top>
    <Bottom>
        <bar>XXX</bar>
    </Bottom>
</Top>

The <Top> would map to the TopNoControlClass and <Bottom> Bottom would map to the BottomNoControlClass and <bar> would map to the foo property of BottomNoControlClass.

将映射到TopNoControlClass, 将映射到Bottom nocontrolclass, 将映射到Bottom nocontrolclass的foo属性。

In order to do the above, I would be comfortable with creating an external XML binding that would state the mappings, but I can't figure a way to use that external binding file in runtime. All the examples I've seen so far only used external XML bindings at generation time (i.e. as a parameter to xjc).

为了完成上述工作,我愿意创建一个外部XML绑定来声明映射,但我无法找到在运行时使用该外部绑定文件的方法。到目前为止,我看到的所有示例都只在生成时使用外部XML绑定(即作为xjc的参数)。

I also wouldn't have a problem with introducing a wrapper class that would override the class names and class property names for the classes it would refer (i.e. TopNoControlClass and BottomNoControlClass). It would be easy to construct the JAXBContext with that class and let JAXB do the rest. But I can't figure out how that annotation should look like.

我也不会对引入一个包装类产生问题,它将覆盖它所引用的类的类名和类属性名(例如TopNoControlClass和BottomNoControlClass)。使用该类构造JAXBContext并让JAXB完成其余的工作是很容易的。但是我不知道那个注释应该是什么样的。

Any help would be greatly appreciated

如有任何帮助,我们将不胜感激

Jaroslav

书中

1 个解决方案

#1


0  

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

注意:我是eclipse JAXB (MOXy)的负责人,也是JAXB (JSR-222)专家组的成员。

In the MOXy implementation of JAXB 2 (JSR-222) we offer an external mapping document for exactly this use case.

在JAXB 2 (JSR-222)的MOXy实现中,我们为这个用例提供了一个外部映射文档。

External Metadata (oxm.xml)

外部元数据(oxm.xml)

Below is what the mapping document would look like for your use case. For the purpose of this example put your model classes in a package called forum13318677. For more information see: http://blog.bdoughan.com/2010/12/extending-jaxb-representing-annotations.html

下面是您用例的映射文档。本例的目的是将模型类放入名为forum13318677的包中。有关更多信息,请参见:http://blog.bdoughan.com/2010/12/extending-jaxb- representtations.html

<?xml version="1.0"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="forum13318677">
    <java-types>
        <java-type name="TopNoControlClass">
            <xml-root-element name="Top"/>
            <xml-type factory-class="forum13318677.Factory" factory-method="createTopNoControlClass"/>
            <java-attributes>
                <xml-element java-attribute="bottomNoControlObject" name="Bottom"/>
            </java-attributes>
        </java-type>
        <java-type name="BottomNoControlClass">
            <xml-type factory-class="forum13318677.Factory" factory-method="createBottomNoControlClass"/>
            <java-attributes>
                <xml-element java-attribute="foo" name="bar"/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

Factory

工厂

Since your model classes did not have 0-argument constructors I needed to create a factory class (see: http://blog.bdoughan.com/2011/06/jaxb-and-factory-methods.html). This class was configured in the XML representation of the @XmlType annotation.

由于您的模型类没有创建工厂类所需的0参数构造函数(请参见:http://blog.bdoughan.com/2011/06/jaxb&factory -methods.html)。这个类是在@XmlType注释的XML表示中配置的。

package forum13318677;

public class Factory {

    public TopNoControlClass createTopNoControlClass() {
        return new TopNoControlClass(null);
    }

    public BottomNoControlClass createBottomNoControlClass() {
        return new BottomNoControlClass(null);
    }

}

jaxb.properties

jaxb.properties

To specify MOXy as your JAXB (JSR-222) provider you need to include a file called jaxb.properties in the same package as your domain classes with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).

要将MOXy指定为JAXB (JSR-222)提供程序,需要包含一个名为JAXB的文件。属性在与域类相同的包中,包含以下条目(参见:http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as your.html)。

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

Demo

演示

The demo code below demonstrates how to leverage MOXy's external mapping document. Note that even though MOXy is used as the JAXB provider there are no compile time dependencies on MOXy.

下面的演示代码演示了如何利用MOXy的外部映射文档。注意,尽管MOXy被用作JAXB提供程序,但是MOXy上没有编译时依赖项。

package forum13318677;

import java.io.File;
import java.util.*;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String,Object>();
        properties.put("eclipselink.oxm.metadata-source", "forum13318677/oxm.xml");
        JAXBContext jc = JAXBContext.newInstance(new Class[] {TopNoControlClass.class}, properties);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum13318677/input.xml");
        TopNoControlClass object = (TopNoControlClass) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(object, System.out);
    }

}

#1


0  

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

注意:我是eclipse JAXB (MOXy)的负责人,也是JAXB (JSR-222)专家组的成员。

In the MOXy implementation of JAXB 2 (JSR-222) we offer an external mapping document for exactly this use case.

在JAXB 2 (JSR-222)的MOXy实现中,我们为这个用例提供了一个外部映射文档。

External Metadata (oxm.xml)

外部元数据(oxm.xml)

Below is what the mapping document would look like for your use case. For the purpose of this example put your model classes in a package called forum13318677. For more information see: http://blog.bdoughan.com/2010/12/extending-jaxb-representing-annotations.html

下面是您用例的映射文档。本例的目的是将模型类放入名为forum13318677的包中。有关更多信息,请参见:http://blog.bdoughan.com/2010/12/extending-jaxb- representtations.html

<?xml version="1.0"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="forum13318677">
    <java-types>
        <java-type name="TopNoControlClass">
            <xml-root-element name="Top"/>
            <xml-type factory-class="forum13318677.Factory" factory-method="createTopNoControlClass"/>
            <java-attributes>
                <xml-element java-attribute="bottomNoControlObject" name="Bottom"/>
            </java-attributes>
        </java-type>
        <java-type name="BottomNoControlClass">
            <xml-type factory-class="forum13318677.Factory" factory-method="createBottomNoControlClass"/>
            <java-attributes>
                <xml-element java-attribute="foo" name="bar"/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

Factory

工厂

Since your model classes did not have 0-argument constructors I needed to create a factory class (see: http://blog.bdoughan.com/2011/06/jaxb-and-factory-methods.html). This class was configured in the XML representation of the @XmlType annotation.

由于您的模型类没有创建工厂类所需的0参数构造函数(请参见:http://blog.bdoughan.com/2011/06/jaxb&factory -methods.html)。这个类是在@XmlType注释的XML表示中配置的。

package forum13318677;

public class Factory {

    public TopNoControlClass createTopNoControlClass() {
        return new TopNoControlClass(null);
    }

    public BottomNoControlClass createBottomNoControlClass() {
        return new BottomNoControlClass(null);
    }

}

jaxb.properties

jaxb.properties

To specify MOXy as your JAXB (JSR-222) provider you need to include a file called jaxb.properties in the same package as your domain classes with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).

要将MOXy指定为JAXB (JSR-222)提供程序,需要包含一个名为JAXB的文件。属性在与域类相同的包中,包含以下条目(参见:http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as your.html)。

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

Demo

演示

The demo code below demonstrates how to leverage MOXy's external mapping document. Note that even though MOXy is used as the JAXB provider there are no compile time dependencies on MOXy.

下面的演示代码演示了如何利用MOXy的外部映射文档。注意,尽管MOXy被用作JAXB提供程序,但是MOXy上没有编译时依赖项。

package forum13318677;

import java.io.File;
import java.util.*;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String,Object>();
        properties.put("eclipselink.oxm.metadata-source", "forum13318677/oxm.xml");
        JAXBContext jc = JAXBContext.newInstance(new Class[] {TopNoControlClass.class}, properties);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum13318677/input.xml");
        TopNoControlClass object = (TopNoControlClass) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(object, System.out);
    }

}