JAXB Маршаллинг с нулевыми полями
Это довольно простой запрос, но я просто не нашел способа сделать это.
Я в основном пытаюсь установить роль в JAXB, которая говорит, что всякий раз, когда встречается пустое поле, вместо игнорирования его в выходных данных, установите его в пустое значение. Итак, для класса:
@XMLRootElement
Class Foo {
Integer num;
Date date;
….
}
Когда это было перенесено в файл XML, если поле даты пустое, мой вывод не содержит этого элемента. Что я хочу сделать, это включить все поля в вывод; и если они нулевые, замените их на - скажем, пустым Таким образом, вывод должен быть:
<foo>
<num>123</num>
<date></date>
</foo>
Спасибо,
Jalpesh.
5 ответов
Спасибо, ребята, за ваши ответы.
Крис Дэйл - я попробовал твой подход, но он не сделал то, что я хотел. 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"/>
....
Но, но... пустая строка не является допустимым лексическим представлением для даты, поэтому вы не можете этого сделать. то есть, если вы сгенерировали XML-документ с пустым значением для поля даты, он не будет проверен надлежащим образом.
Другими словами, если ваш date
элемент имеет minOccurs
из 1 или более и не nillable
, тогда у вас обязательно должны быть (1 или более) даты, которые не могут быть нулевыми (или пробелами, или другими ненулевыми значениями).
Как указано в другом ответе является недействительным, так как это не является действительной датой. У меня была похожая проблема, в которой я специально хотел (так же, как) решить. Поскольку вы не можете использовать нуль, вы можете использовать механизм значений по умолчанию в JAXB. Следующее будет значение по умолчанию, если ничего не указано. Вы можете с помощью кода обнаружить эту особую дату и обработать это исключение.
@XmlElement(defaultValue="1970-01-01T00:00:00.0-00:00")
Таким образом, можно обнаружить и очистить значение даты, но вы просто не можете использовать ноль для этого.
В 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 на уровне сервера приложений, если это вообще возможно.
Попробуй это:
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();
}
}
}
}