Можете ли вы изменить значение по умолчанию атрибута nillable в JAXB? - PullRequest
6 голосов
/ 12 января 2012

Я рефакторинг некоторого кода для использования JAXB и отражения для вывода кода на клиент, в настоящее время он использует XMLWriter и каждый раз вручную создает теги.

Проблема, с которой я сталкиваюсь, заключается в том, что из-за ограничений на стороне клиента мне нужно иметь пустые элементы в XML для любых пустых полей в классе java.

Хотя я понимаю, что эту проблему можно решить, добавив nillable=true к каждой аннотации JAXB XmlElement, но это не самое практичное решение, поскольку у меня есть много таких аннотаций.

Я надеялся найти способ установить nillable=true в качестве глобального атрибута (или в качестве значения по умолчанию).Это также облегчит будущим коллегам работу над ним, поскольку им не нужно будет помнить, что каждая аннотация должна включать атрибут nillable.

Я не нашел ничего кроме описаний по умолчаниюповедение.Я нахожу удивительным, что никто другой не публиковал подобный вопрос в прошлом.Из того, что я обнаружил, мне не кажется, что есть встроенная поддержка для настройки по умолчанию.Это может быть решено с помощью пользовательской реализации JAXB или, возможно, сторонней реализации JAXB?

1 Ответ

1 голос
/ 13 января 2012

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

Я ввел запрос на улучшение, чтобы добавить это поведение в EclipseLink JAXB (MOXy):

РАБОТА В РАМКАХ

В качестве обходного пути, если все ваши сопоставленные поля / свойства String сопоставлены с элементами XML, тогда может пригодиться следующий подход XmlAdapter:

NullStringAdapter

Этот XmlAdapter будет маршалировать экземпляры String как объект с именем AdaptedString.AdaptedString содержит значение String, а также поле, сопоставленное с атрибутом xsi:nilXmlAdapter мы установим значение этого поля в зависимости от того, является ли значение String нулевым.

package forum8841221;

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

public class NullStringAdapter extends XmlAdapter<NullStringAdapter.AdaptedString, String> {

    @Override
    public AdaptedString marshal(String v) throws Exception {
        AdaptedString adaptedString = new AdaptedString();
        if(null == v) {
            adaptedString.nil = true;
        }
        adaptedString.value = v;
        return adaptedString;
    }

    @Override
    public String unmarshal(AdaptedString v) throws Exception {
        return v.value;
    }

    public static class AdaptedString {

        @XmlAttribute(namespace="http://www.w3.org/2001/XMLSchema-instance")
        public Boolean nil;

        @XmlValue
        @XmlJavaTypeAdapter(VoidStringAdapter.class)
        public String value;

    }

    public static class VoidStringAdapter extends XmlAdapter<String, String> {

        @Override
        public String marshal(String v) throws Exception {
            return v;
        }

        @Override
        public String unmarshal(String v) throws Exception {
            return v;
        }

    }

}

package-info

Мы можем зарегистрировать, что мы хотим, чтобы этот XmlAdapter применялся ко всем сопоставленным String полям / свойствам в этом пакете, зарегистрировав XmlAdapter на уровне пакета.

@XmlJavaTypeAdapter(value=NullStringAdapter.class, type=String.class)
@XmlSchema(xmlns={@XmlNs(namespaceURI = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi")})
package forum8841221;

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

Root

Ниже приведен класс домена, который я использовал для этого примера.У него есть несколько свойств String, одно из них снабжено аннотацией @XmlElement (nillable = true)

package forum8841221;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Root {

    private String a;
    private String b;
    private String c;
    private String d;

    public String getA() {
        return a;
    }

    public void setA(String a) {
        this.a = a;
    }

    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }

    public String getC() {
        return c;
    }

    public void setC(String c) {
        this.c = c;
    }

    @XmlElement(nillable=true)
    public String getD() {
        return d;
    }

    public void setD(String d) {
        this.d = d;
    }

}

Демонстрация

package forum8841221;

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

        Root root = new Root();
        root.setB("B");

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

Вывод

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <a xsi:nil="true"/>
   <b>B</b>
   <c xsi:nil="true"/>
   <d xsi:nil="true"/>
</root>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...