简体   繁体   English

使用FIELD访问器类型覆盖@XmlElement注释

[英]override @XmlElement annotation with FIELD accessor type

I have a class with @XmlAccessorType(XmlAccessType.FIELD) annotation, and each private and protected field is annotated with @XmlElement(name='...') . 我有一个带有@XmlAccessorType(XmlAccessType.FIELD)注释的类,每个privateprotected字段都用@XmlElement(name='...')注释。

The challenge: I may want to rename one of the xml element names in a later stage. 挑战:我可能想在稍后阶段重命名一个xml元素名称。 This leads me to the question. 这引出了我的问题。 Is there a way to override/redefine these annotations, if I create a sub-class ? 如果我创建一个子类,有没有办法覆盖/重新定义这些注释?

Whilst in java, to my knowledge, overriding an annotation @XmlElement(name='...') to change the name property is not possible; 虽然在java中,据我所知,重写注释@XmlElement(name='...')来更改name属性是不可能的; you can create a global variable in your code and either pass it through your classes or your functions following the @XmlElement(name='...') . 您可以在代码中创建一个全局变量,并将其传递给您的类或@XmlElement(name='...')之后的函数。

In the code below I created a single class but it contains the setter and getter methods required if you want to pass it through to another class 在下面的代码中,我创建了一个单独的类,但如果你想将它传递给另一个类,它包含所需的setter和getter方法

@XMLAccessorType(XMLAccessType.FIELD)
public class YourClass {

    @XmlTransient
    private String string = ""; //This can be replaced with whatever variable you are manipulating
                                //That could be an int or a file or anything really

    @XmlElement(name = "your_name")
    private void doSomething() {
        String temp = getString(); //This variable is normally used to pass between different
                                   //classes but may as well use it if you have one
        //Your code which manipulates the String
        setString(temp); //This variable is normally used to pass between different classes but
                         //may as well use it if you have one
    }


    @XmlElement(name = "your_other_name")
    private void doSomethingElse() {
        String temp = getString();
        //Your code which manipulates the String
        setString(temp);
    }

    public void getString() {
        return string;
    }


    public void setString(String string) {
        this.string = string;
    }

}

I would reccomend looking at the Java Docs for @XmlTransient and these two other relevant SO questions. 我会建议查看Java Docs for @XmlTransient以及这两个相关的SO问题。

How to override JAXB @XMLAccessorType(XMLAccessType.FIELD) specified at a Class level with @XMLElement on a getter method for a property? 如何在属性的getter方法上使用@XMLElement覆盖在类级别指定的JAXB @XMLAccessorType(XMLAccessType.FIELD)?

Jaxb - Overriding the XMLElement name attribute Jaxb - 覆盖XMLElement名称属性

I tried first with the @XmlAccessorType(XmlAccessType.FIELD) and to hide with @XmlTransient . 我首先尝试使用@XmlAccessorType(XmlAccessType.FIELD)并使用@XmlTransient隐藏。 This only works, if you mark the field in the superclass and in the child class with @XmlTransient . 只有在使用@XmlTransient标记超类和子类中的字段时, @XmlTransient But I assume, this is not what you want. 但我想,这不是你想要的。

As second approach I've tried with more restrictive @XmlAccessorType(XmlAccessType.PROPERTY) in the superclass and @XmlAccessorType(XmlAccessType.NONE) in the child class. 作为第二种方法,我尝试在超类中使用更严格的@XmlAccessorType(XmlAccessType.PROPERTY) ,在子类中使用@XmlAccessorType(XmlAccessType.NONE) See here my example: 看到我的例子:

package com.so.example;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/myresource")
public class MyResource {

    @GET
    @Path("/car")
    @Produces(MediaType.APPLICATION_XML)
    public Car getCar() {
        Car car = new Car();
        car.setWheels(4);
        return car;
    }

    @GET
    @Path("/suv")
    @Produces(MediaType.APPLICATION_XML)
    public Suv getSuv() {
        Suv suv = new Suv();
        List<String> bigWheels = new ArrayList<>();
        bigWheels.add("left front wheel");
        bigWheels.add("right front wheel");
        bigWheels.add("left rear wheel");
        bigWheels.add("right rear wheel");
        suv.setBigWheels(bigWheels);
        return suv;
    }
}

Class Car: 类车:

package com.so.example;

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.PROPERTY)
@XmlRootElement
public class Car {

    protected Integer wheels;

    public Car() {
    }

    @XmlElement(name = "wheels", nillable = true)
    public Integer getWheels() {
        return wheels;
    }

    public void setWheels(Integer wheels) {
        this.wheels = wheels;
    }
}

Class Suv (Child): Suv(儿童)班:

package com.so.example;

import java.util.List;

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

@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class Suv extends Car {

    @XmlTransient
    private Integer wheels;

    private List<String> bigWheels;

    public Suv() {
    }

    @Override
    @XmlTransient
    public Integer getWheels() {
        return wheels;
    }

    @Override
    public void setWheels(Integer wheels) {
        this.wheels = wheels;
    }

    @XmlElement
    public List<String> getBigWheels() {
        return bigWheels;
    }

    public void setBigWheels(List<String> bigWheels) {
        this.bigWheels = bigWheels;
    }
}

One way to "hide" the element wheels of the superclass would be to mark it as "nillable=true" and not use primitive types. “隐藏”超类的元素轮的一种方法是将其标记为“nillable = true”而不使用基本类型。 In this case, the field wheels will be marshalled to <wheels xsi:nil="true"/> 在这种情况下,现场车轮将被编组为<wheels xsi:nil="true"/>

If it's possible for you to not use the parent class for marshalling and you are only using child classes, you could use the approach described here: 如果您可以不使用父类进行编组,并且您只使用子类,则可以使用此处描述的方法:

http://blog.bdoughan.com/2011/06/ignoring-inheritance-with-xmltransient.html http://blog.bdoughan.com/2011/06/ignoring-inheritance-with-xmltransient.html

Also you could use moxy and specify a custom binding: http://www.eclipse.org/eclipselink/documentation/2.4/moxy/runtime003.htm 您也可以使用moxy并指定自定义绑定: http//www.eclipse.org/eclipselink/documentation/2.4/moxy/runtime003.htm

I believe that some implementations of JaxB allow for XML configuration to override the annotations. 我相信JaxB的某些实现允许XML配置覆盖注释。 In this case this may actually be possible. 在这种情况下,这实际上是可能的。 Here is an article from Eclipslink explaining how this can be done http://www.eclipse.org/eclipselink/documentation/2.4/solutions/jpatoxml004.htm 以下是Eclipslink的一篇文章,解释了如何做到这一点http://www.eclipse.org/eclipselink/documentation/2.4/solutions/jpatoxml004.htm

In my opinion you can just build an XML configuration for the JaxB file you want to override. 在我看来,您可以为要覆盖的JaxB文件构建XML配置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM