JAXB 和构造函数

发布于 2024-10-06 07:31:31 字数 377 浏览 0 评论 0原文

我正在开始学习 JAXB,所以我的问题可能很愚蠢。现在我有类并且想要生成 XML 模式。遵循 this 指令我得到异常

IllegalAnnotationExceptions ...没有无参数默认值 构造函数。

是的。我的类没有默认的无参数构造函数。这太容易了。我有一些带有包可见构造函数/最终方法的类,当然也带有参数。我应该做什么 - 创建一些特定的 momemto/builder 类或向 JAXB 指定我的构造函数(以什么方式?)?谢谢。

I'm starting learning JAXB, so my question can be very silly. Now I have classes and want generate XML Schema. Going after this instruction I get exception

IllegalAnnotationExceptions ... does not have a no-arg default
constructor.

Yeah. My classes haven't default no-arg constructors. It's too easy. I have classes with package visible constructors / final methods and off course with arguments. What shall I do - create some specific momemto/builder classes or specify my constructors to JAXB (in what way?) ? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

花开半夏魅人心 2024-10-13 07:31:31

JAXB 可以使用 XML 适配器支持这种情况。假设您有以下没有零参数构造函数的对象:

package blog.immutable;

public class Customer {

    private final String name;
    private final Address address;

    public Customer(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public Address getAddress() {
        return address;
    }

}

您只需创建此类的可映射版本:

package blog.immutable.adpater;

import javax.xml.bind.annotation.XmlAttribute;
import blog.immutable.Address;

public class AdaptedCustomer {

    private String name;
    private Address address;

    @XmlAttribute
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

}

以及一个在它们之间进行转换的 XML 适配器:

package blog.immutable.adpater;

import javax.xml.bind.annotation.adapters.XmlAdapter;
import blog.immutable.Customer;

public class CustomerAdapter extends XmlAdapter<AdaptedCustomer, Customer> {

    @Override
    public Customer unmarshal(AdaptedCustomer adaptedCustomer) throws Exception {
        return new Customer(adaptedCustomer.getName(), adaptedCustomer.getAddress());
    }

    @Override
    public AdaptedCustomer marshal(Customer customer) throws Exception {
        AdaptedCustomer adaptedCustomer = new AdaptedCustomer();
        adaptedCustomer.setName(customer.getName());
        adaptedCustomer.setAddress(customer.getAddress());
        return adaptedCustomer;
    }

}

然后,对于引用 Customer 类的属性,只需使用 @XmlJavaTypeAdapter 注释:

package blog.immutable;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import blog.immutable.adpater.CustomerAdapter;

@XmlRootElement(name="purchase-order")
public class PurchaseOrder {

    private Customer customer;

    @XmlJavaTypeAdapter(CustomerAdapter.class)
    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

} 

有关更详细的示例,请参阅:

JAXB can support this case using an XML Adapter. Consider you have the following object with no zero-arg constructor:

package blog.immutable;

public class Customer {

    private final String name;
    private final Address address;

    public Customer(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public Address getAddress() {
        return address;
    }

}

You simply need to create a mappable version of this class:

package blog.immutable.adpater;

import javax.xml.bind.annotation.XmlAttribute;
import blog.immutable.Address;

public class AdaptedCustomer {

    private String name;
    private Address address;

    @XmlAttribute
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

}

And an XML Adapter to convert between them:

package blog.immutable.adpater;

import javax.xml.bind.annotation.adapters.XmlAdapter;
import blog.immutable.Customer;

public class CustomerAdapter extends XmlAdapter<AdaptedCustomer, Customer> {

    @Override
    public Customer unmarshal(AdaptedCustomer adaptedCustomer) throws Exception {
        return new Customer(adaptedCustomer.getName(), adaptedCustomer.getAddress());
    }

    @Override
    public AdaptedCustomer marshal(Customer customer) throws Exception {
        AdaptedCustomer adaptedCustomer = new AdaptedCustomer();
        adaptedCustomer.setName(customer.getName());
        adaptedCustomer.setAddress(customer.getAddress());
        return adaptedCustomer;
    }

}

Then for properties that refer to the Customer class, simply use the @XmlJavaTypeAdapter annotation:

package blog.immutable;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import blog.immutable.adpater.CustomerAdapter;

@XmlRootElement(name="purchase-order")
public class PurchaseOrder {

    private Customer customer;

    @XmlJavaTypeAdapter(CustomerAdapter.class)
    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

} 

For a more detailed example see:

野侃 2024-10-13 07:31:31

您可以使用注释@XmlType并以各种组合使用factoryMethod/factoryClass属性,例如:

@XmlType(factoryMethod="newInstance")
@XmlRootElement
public class PurchaseOrder {
    @XmlElement
    private final String address;
    @XmlElement
    private final Customer customer;

    public PurchaseOrder(String address, Customer customer){
        this.address = address;
        this.customer = customer;
    }

    private PurchaseOrder(){
        this.address = null;
        this.customer = null;
    }
    /** Creates a new instance, will only be used by Jaxb. */
    private static PurchaseOrder newInstance() {
        return new PurchaseOrder();
    }

    public String getAddress() {
        return address;
    }

    public Customer getCustomer() {
        return customer;
    }
}

令人惊讶的是,这有效,并且在解组时您会获得一个初始化的实例。您应该注意不要在代码中的任何位置调用 newInstance 方法,因为它将返回无效实例。

You can use the annotation @XmlType and use factoryMethod / factoryClass attributes in various combinations such as:

@XmlType(factoryMethod="newInstance")
@XmlRootElement
public class PurchaseOrder {
    @XmlElement
    private final String address;
    @XmlElement
    private final Customer customer;

    public PurchaseOrder(String address, Customer customer){
        this.address = address;
        this.customer = customer;
    }

    private PurchaseOrder(){
        this.address = null;
        this.customer = null;
    }
    /** Creates a new instance, will only be used by Jaxb. */
    private static PurchaseOrder newInstance() {
        return new PurchaseOrder();
    }

    public String getAddress() {
        return address;
    }

    public Customer getCustomer() {
        return customer;
    }
}

Surprisingly this works and you get an initialized instance when unmarshalling. You should make note not to call the newInstance method anywhere on your code as it will return an invalid instance.

人│生佛魔见 2024-10-13 07:31:31

您应该有一个 JAXB 的默认构造函数,以便能够实例化您的类。也许有一个我不知道的解决方法。

JAXB 特别适合类 Bean 类,允许通过调用对象的 setter 来配置对象。

You should have a default constructor for JAXB to be able to instantiate your classes. Maybe there is a workaround I don't know though.

JAXB is especially fitted for bean-like classes, permitting to configure objects by calling setters on them.

不打扰别人 2024-10-13 07:31:31

JAXB 以简单的方式从 XML 重新创建 bean:它创建 bean 的新实例,然后执行设置属性所需的所有 setXXX 操作。因此,如果您的 bean 没有无参数构造函数,JAXB 就无法创建它。正如其他答案中所述,JAXB 对于简单的“容器”bean 效果更好,对于这种情况,无参数构造函数并不是真正的问题。如果您尝试创建需要特定初始化的 bean,则需要在 setXXX 方法中执行此操作。

JAXB re-creates beans from XML in a simple fashion : it creates a new instance of the bean, and then do all the setXXX needed to set the attributes. So, if your bean doesn't have a no-args constructor, JAXB can't create it. As said in other answers, JAXB works better for simple "container" beans, for which no-args constructor isn't really a problem. If you're trying to create beans that need specific initialization, you'll need to do it in the setXXX methods.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文