JAXB + Enums + Отображение нескольких значений - PullRequest
5 голосов
/ 14 сентября 2010

У меня есть enum:

@XmlEnum
@XmlRootElement
public enum Product {
    POKER("favourite-product-poker"),
    SPORTSBOOK("favourite-product-casino"),
    CASINO("favourite-product-sportsbook"),
    SKILL_GAMES("favourite-product-skill-games");

    private static final String COULD_NOT_FIND_PRODUCT = "Could not find product: ";

    private String key;

    private Product(final String key) {
        this.key = key;
    }

    /**
     * @return the key
     */
    public String getKey() {
        return key;
    }

, который я выводил в REST-сервисе примерно так:

GenericEntity<List<Product>> genericEntity = new GenericEntity<List<Product>>(products) {
};
return Response.ok().entity(genericEntity).build();

, и он выводил вот так:

<products>
<product>POKER</product>
<product>SPORTSBOOK</product>
<product>CASINO</product>
<product>SKILL_GAMES</product>
</products>

Я хочу, чтобы он выводился как с именем enum (то есть, POKER), так и с ключом (то есть, «favour-product-poker»).

Я пробовал несколько различных способов сделать это, включая использование @XmlElement, @XmlEnumValue и @XmlJavaTypeAdapter, не вынимая оба одновременно.

Кто-нибудь знает, как этого добитьсякак вы бы сделали для обычного JAXB-аннотированного компонента?

Спасибо.

Ответы [ 3 ]

4 голосов
/ 14 сентября 2010

Вы можете создать для этого объект-оболочку, например:

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;

@XmlRootElement(name="product")
public class ProductWrapper {

    private Product product;

    @XmlValue
    public Product getValue() {
        return product;
    }

    public void setValue(Product value) {
        this.product = value;
    }

    @XmlAttribute
    public String getKey() {
        return product.getKey();
    }

}

Это будет соответствовать следующему XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<product key="favourite-product-poker">POKER</product>

Вам потребуется передать экземпляры ProductWrapper в JAXB вместо Product.

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(ProductWrapper.class);

        ProductWrapper pw = new ProductWrapper();
        pw.setValue(Product.POKER);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.marshal(pw, System.out);
    }

}
2 голосов
/ 15 ноября 2010

Вы можете использовать адаптер:

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlValue;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

public class XmlEnumTest{

    public static void main(String...str) throws Exception{
        JAXBContext jc = JAXBContext.newInstance(ProductList.class);
        StringWriter sw = new StringWriter();
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(new ProductList(),sw);
        System.out.println(sw.toString());
    }
}

class ProductTypeAdaper  extends XmlAdapter<ProductAdapter, Product> {
    @Override
    public Product unmarshal(ProductAdapter v) throws Exception {
        return Product.valueOf(v.value);
    }

    @Override
    public ProductAdapter marshal(Product v) throws Exception {
        ProductAdapter result = new ProductAdapter();
        result.key = v.getKey();
        result.value = v.name();
        return result;
    }
}

@XmlType
class ProductAdapter{
    @XmlAttribute
    public String key;
    @XmlValue
    public String value;
}

@XmlJavaTypeAdapter(ProductTypeAdaper.class)
enum Product{
    POKER("favourite-product-poker"),
    SPORTSBOOK("favourite-product-casino"),
    CASINO("favourite-product-sportsbook"),
    SKILL_GAMES("favourite-product-skill-games");

    private static final String COULD_NOT_FIND_PRODUCT = "Could not find product: ";

    private String key;

    private Product(final String key) {
        this.key = key;
    }

    /**
     * @return the key
     */
    public String getKey() {
        return key;
    }

}

@XmlRootElement
@XmlSeeAlso({Product.class})
class ProductList{
    @XmlElementWrapper(name="products")
    @XmlElement(name="product")
    private List<Product> list = new ArrayList<Product>(){{add(Product.POKER);add(Product.SPORTSBOOK);add(Product.CASINO);}};
}
0 голосов
/ 19 октября 2010

Вам необходимо удалить @XmlEnum из значения enum, если вы хотите, чтобы он был сериализован в XML, как обычный объект. Перечисление (по определению) представлено в XML одним символом строки. Это позволяет комбинировать его с @XmlList, например, для создания эффективного списка элементов, разделенных пробелами.

...