使用空字段的JAXB编组

时间:2009-05-13 15:16:39

标签: java jaxb marshalling

这是一个非常简单的请求,但我没有办法做到这一点。

我基本上试图在JAXB中设置一个角色,它表示只要遇到空字段,而不是在输出中忽略它,就将其设置为空值。所以对于班级来说:

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

如果日期字段为null,那么当它被编组到XML文件中时,我的输出中没有该元素。我想要做的是包括输出中的所有字段;如果它们为null,则将它们替换为 - 例如空白。所以输出应该是:

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

谢谢,

Jalpesh。

5 个答案:

答案 0 :(得分:39)

谢谢你的回答。

Chris Dail - 我试过你的方法,但它并没有真正做到我想要的。尽管为我的字段定义了默认值,JAXB仍然忽略了我的空值。

在泽西论坛的某个人向我指出文档部分2.2.12.8 No Value之后,我偶然发现了答案。

基本上,我所要做的就是将以下内容添加到我的字段中:

@XmlElement(nillable = true) 

一旦我添加了它,JAXB会在将它们编组为XML时显示这些字段:

...
<num>5</num>
<date xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
....

答案 1 :(得分:4)

但是但是......空字符串不是日期的有效词汇表示,所以你不能这样做。即,如果您为日期字段生成了一个空值的XML文档,则它将无法正确验证。

换句话说,如果您的date元素的minOccurs为1或更多,而不是nillable,那么您绝对必须拥有(1个或更多)日期,而不能为null(或空格或其他非值)。

答案 2 :(得分:2)

如其他答案中所示,由于它不是有效日期,因此无效。我有一个类似的问题,我想特别处理(相同)。由于您不能使用null,因此可以在JAXB中使用默认值机制。如果未指定,则以下将默认值。您可以通过代码检测此特殊日期并处理此异常情况。

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

因此可以检测并清空日期值,但您不能使用null来执行此操作。

答案 3 :(得分:1)

在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提供程序。 对于带有MOXy的Glassfish,我目睹了null值的相同问题。 还没有检查,但猜测答案是在应用程序服务器级别配置JAXB,如果可能的话。

答案 4 :(得分:0)

尝试一下:

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();
            }
        }
    }
}