JAXB Маршаллинг с пустыми полями - PullRequest
48 голосов
/ 13 мая 2009

Это довольно простой запрос, но я просто не нашел способа сделать это.

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

@XMLRootElement
Class Foo {
   Integer num;
   Date date;
….
}

Когда это было перенесено в файл XML, если поле даты пустое, мои выходные данные не содержат этого элемента. Что я хочу сделать, это включить все поля в вывод; и если они нулевые, замените их на - скажем, пробел. Таким образом, вывод должен быть:

<foo>
  <num>123</num>
  <date></date>
</foo>

Спасибо

Jalpesh.

Ответы [ 5 ]

39 голосов
/ 14 мая 2009

Спасибо, ребята, за ваши ответы.

Крис Дэйл - я попробовал твой подход, но он не сделал то, что я хотел. JAXB все еще игнорировал мои нулевые значения, несмотря на определение значения по умолчанию для моих полей.

Я наткнулся на ответ после того, как кто-то на форумах Джерси указал мне на раздел документации 2.2.12.8 Нет значения .

По сути, все, что мне нужно было сделать, это добавить следующее в мои поля:

@XmlElement(nillable = true) 

Как только я добавлю это, JAXB отобразит эти поля при сортировке их в XML следующим образом:

...
<num>5</num>
<date xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
....
4 голосов
/ 13 мая 2009

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

Другими словами, если ваш date элемент имеет minOccurs, равное 1 или более, а не nillable, то у вас обязательно должны быть (1 или более) даты, которые не могут быть нулевыми (или пробелами или другие ненулевые значения).

2 голосов
/ 13 мая 2009

Как указано в другом ответе, недействительно, так как это недопустимая дата. У меня была похожая проблема, в которой я хотел решить (так же, как) специально. Поскольку вы не можете использовать нуль, вы можете использовать механизм значений по умолчанию в JAXB. Следующее будет значение по умолчанию, если ничего не указано. Вы можете с помощью кода обнаружить эту особую дату и обработать это исключение.

@XmlElement(defaultValue="1970-01-01T00:00:00.0-00:00")

Таким образом, можно определить и очистить значение даты, но вы просто не можете использовать ноль для этого.

1 голос
/ 05 марта 2013

В MOXy вы можете указать, как jsonProvider должен выполнять свою работу для JAXB.

Поэтому, когда вы выполняете JAX-RS, добавьте следующий код в ваш класс, полученный из Application

Я использовал этот код на Tomcat 7 с хорошими результатами. (eclipselink 2.4.1)

@ApplicationPath("/rest")
public class RestApplication extends Application
{

  ...

 public Set< Object> getSingletons()
  {

    HashSet<Object> set = new HashSet<Object>(1);
    set.add( newMoxyJsonProvider());

    return set;
  }


 public static MOXyJsonProvider newMoxyJsonProvider()
  {

    MOXyJsonProvider result = new MOXyJsonProvider();

    //result.setAttributePrefix("@");
    result.setFormattedOutput( false);
    result.setIncludeRoot( false);
    result.setMarshalEmptyCollections( true);
    //result.setValueWrapper("$");

    return result;
  }

В Glassfish 3.1.2 и WAS 8.5, однако, newMoxyJsonProvider () не нужен, но тогда провайдер JAXB настраивается сервером. В случае Glassfish, который поставляется с MOXy, у меня были те же проблемы с нулевыми значениями. Еще не проверял, но думаю, что ответ в настройке JAXB на уровне сервера приложений, если это вообще возможно.

0 голосов
/ 30 августа 2018

Попробуйте это:

marshal.setListener(new MarshallerListener());

с

public class MarshallerListener extends Marshaller.Listener {

    public static final String BLANK_CHAR = "";

    @Override
    public void beforeMarshal(Object source) {
        super.beforeMarshal(source);
        Field[] fields = source.getClass().getDeclaredFields();
        for (Field f : fields) {
            f.setAccessible(true);
            try {
                if (f.getType() == String.class && f.get(source) == null) {
                    f.set(source, BLANK_CHAR);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}
...