Как позволить JAXB исключить пустой узел?

Я использую JAXB для сериализации объектов в XML. Теперь я понимаю, что это исключит естественные нулевые значения из ответа, но не исключит нулевые значения из настроенных адаптеров. Ниже мой код.

package com.model;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class JAXBTest {

public static void main(String[] args) throws JAXBException {
    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.setAdapter(BooleanAdapter.class,new BooleanAdapter(true));
    marshaller.marshal(thing, System.out);

}

@XmlRootElement 
public static class Thing{
    private String name;
    private Boolean awesome;
    private String empty;

    public String getEmpty() {
        return empty;
    }
    public void setEmpty(String empty) {
        this.empty = empty;
    }

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

    public void setAwesome(Boolean awesome) {
        this.awesome = awesome;
    }
    public Boolean isAwesome() {
        return this.awesome;
    }
}

public static class BooleanAdapter extends XmlAdapter<String, Boolean> {

    boolean flag;

    public BooleanAdapter(boolean flag){
        this.flag = flag;
    }

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

    public String marshal(Boolean v) throws Exception {
        if(flag){
             if(v) {
                return v.toString();
            }
            return null;
        }else{
            return v.toString();
        }          
    }
}
}

packageinfo.java:

@XmlJavaTypeAdapter(value=JAXBTest.BooleanAdapter.class, type=Boolean.class)
package com.model;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

Выход:

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

Как видите, даже я возвращаю ноль в адаптере, в ответе все еще есть пустой узел awesome /. Естественное нулевое поле "private String empty" полностью игнорируется. Итак, мой вопрос, как исключить эти пустые узлы из ответа?

1 ответ

Для элемента используйте пустой класс, а не String, только адаптируйте TRUE к вашему классу. (Может быть new Object() будет работать, но я не пробовал это.)

public class BooleanXmlElement {

    public BooleanXmlElement() {
    }


    public static class Adapter extends XmlAdapter<BooleanXmlElement, Boolean> {

        public Boolean unmarshal(BooleanXmlElement v) {
            return Boolean.TRUE;
        }

        public BooleanXmlElement marshal(Boolean v) {
            if (Boolean.TRUE.equals(v)) {
                return new BooleanXmlElement();
            }
            return null;
        }
    }
}

Это не работает для атрибутов, однако, для них String кажется необходимым:

public class BooleanXmlAttribute extends XmlAdapter<String, Boolean> {

    public Boolean unmarshal(String v) {
        return Boolean.valueOf(v);
    }

    public String marshal(Boolean v) {
        if (Boolean.TRUE.equals(v)) {
            return Boolean.TRUE.toString();
        }
        return null;
    }
}

Чтобы покрыть оба Boolean а также boolean Аннотируйте ваш пакет для обоих:

@XmlJavaTypeAdapters({
    @XmlJavaTypeAdapter(value=BooleanXmlElement.Adapter.class, type=boolean.class),
    @XmlJavaTypeAdapter(value=BooleanXmlElement.Adapter.class, type=Boolean.class)
})
package com.model;

Редактировать: удалить строку:

marshaller.setAdapter(BooleanAdapter.class,new BooleanAdapter(true));

тебе это не нужно

Другие вопросы по тегам