JAXB - подавить логический атрибут, если false - PullRequest
7 голосов
/ 02 июля 2011

Допустим, у меня есть класс

@XmlRootElement(name="thing")
public class Thing{
    private String name;
    private boolean awesome;

    @XmlValue public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return this.value;
    }


    @XmlAttribute public void setAwesome(boolean awesome) {
        this.awesome = awesome;
    }
    public boolean isAwesome() {
        return this.awesome;
    }
}

Если я создаю некоторые вещи, а затем собираю их в XML, это выглядит так:

Летающий ниндзя:

<thing awesome="true">flying ninja</thing>

Обычный старый шар попкорна:

<thing awesome="false">popcorn ball</thing>

Но ... я бы хотел изменить способ сортировки моих логических атрибутов.Я бы предпочел, чтобы шар для попкорна выглядел следующим образом, подавляя потрясающий атрибут:

<thing>popcorn ball</thing>

Как я могу это сделать?

Большое спасибо!

Ответы [ 4 ]

8 голосов
/ 04 июля 2011

Примечание: Я являюсь лидером EclipseLink JAXB (MOXy) и членом группы экспертов JAXB 2.X ( JSR-222 ) .

Используя MOXy, вы можете использовать XmlAdapter подход, предложенный Hovercraft Full Of Eels . Это будет выглядеть примерно так:

BooleanAdapter

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class BooleanAdapter extends XmlAdapter<Boolean, Boolean> {

    @Override
    public Boolean unmarshal(Boolean v) throws Exception {
        return Boolean.TRUE.equals(v);
    }

    @Override
    public Boolean marshal(Boolean v) throws Exception {
        if(v) {
            return v;
        }
        return null;
    }

}

Thing

Вы связываете свою собственность с XmlAdapter, используя аннотацию @XmlJavaTypeAdapter следующим образом:

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

@XmlRootElement(name="thing")
public class Thing{
    private String name;
    private boolean awesome;

    @XmlValue public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return this.name;
    }


    @XmlAttribute
    @XmlJavaTypeAdapter(BooleanAdapter.class)
    public void setAwesome(boolean awesome) {
        this.awesome = awesome;
    }
    public boolean isAwesome() {
        return this.awesome;
    }
}

Демо

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(Thing.class);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        Thing thing = new Thing();
        thing.setName("popcorn ball");

        thing.setAwesome(false);
        marshaller.marshal(thing, System.out);

        thing.setAwesome(true);
        marshaller.marshal(thing, System.out);
    }

}

выход

<?xml version="1.0" encoding="UTF-8"?>
<thing>popcorn ball</thing>
<?xml version="1.0" encoding="UTF-8"?>
<thing awesome="true">popcorn ball</thing>

Использование JAXB RI

Если вы запустите этот пример с JAXB RI, вы получите следующее исключение:

Exception in thread "main" com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Adapter example.BooleanAdapter is not applicable to the field type boolean. 
    this problem is related to the following location:
        at @javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(type=class javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter$DEFAULT, value=class example.BooleanAdapter)
        at public boolean example.Thing.isAwesome()
        at forum251.Thing

Для получения дополнительной информации

3 голосов
/ 08 сентября 2015

Достигните этого, используя обнуляемый тип и зарегистрировав JAXB-слушатель для вашего класса.Внутри слушателя JAXB установите свой атрибут на null, если вы не хотите его маршалировать.Этот подход должен работать в любой реализации JAXB.

Ваш (логический или другой) атрибут

@XmlAttribute(required = false)
private Boolean valueUnknown;

Обработчик JAXB beforeMarshal

@SuppressWarnings("PMD")
private void beforeMarshal(final Marshaller marshaller) {
    // Remove the "valueUnknown" attribute if it is not true.
    // Assigning a null value implies that the attribute is removed.
    if(!valueUnknown) {
        valueUnknown = null;
    }
}

Этот подход может, например,- дать результат ниже.Обратите внимание, что атрибут valueUnknown присутствует только в том случае, если не указан атрибут value.

    <items>
        <item xsi:type="eduDataExchange:compoundValue" valueUnknown="true"/>
        <item xsi:type="eduDataExchange:compoundValue" value="4" percentage="3"/>
    </items>
1 голос
/ 02 июля 2011

Я не знаком с JAXB (пока), но обычно такого рода вещи вполне могут быть выполнимы при обработке XSLT или преобразовании.

Кроме того, в ответе на этот вопрос упоминается использование XmlAdapter, который, по-видимому, непосредственно применим к вашей проблеме: Как разрешить JAXB отображать логические значения 0 и 1, а не true и false

0 голосов
/ 07 февраля 2017

заменив логическое значение логическим объектом, я решил эту проблему для меня.

Использование: -

private Boolean awesome;

вместо: -

private boolean awesome;
...