使用与xml适配器一起使用的自定义类型对空值进行编组

时间:2012-05-02 13:47:00

标签: java jaxb jersey

我正在使用带有XmlType的POJO对象作为我为编组字符串映射而构建的自定义XML适配器。但是我遇到了问题,因为我允许我正确使用空值。我能够让它工作,但我对它产生的XML不满意。

这就是我目前正在使用的工作,但正如您在XML结果示例中所看到的那样,它不包括正确的xmlns:xsi =“http://www.w3.org/ 2001 / XMLSchema-instance“xsi:nil =”true“value

@XmlType(name="element")
public class RestMapElements {

  @XmlAttribute(name="name")
  public String key;
  @XmlValue
  public String value;

  public RestMapElements(String key, String value) {
    this.key = key;
    this.value = value;
  }
}

生成的XML(精简到相关数据)。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
...
    <element-list>
        <item name="activated_date">2012-03-29 11:34:14.323</item>
        <item name="some_null_value"/>
    </element-list>
...

但是,我能够使用它,我只是不满意XML必须在item标签内添加额外的“value”标签才能使其工作。 (旁注,为什么它命名为item而不是像我试图在XmlType名称声明中指定的元素?)

@XmlType(name="element")
public class RestMapElements {

  @XmlAttribute(name="name")
  public String key;
  @XmlElement(nillable = true)
  public String value;

  public RestMapElements(String key, String value) {
    this.key = key;
    this.value = value;
  }
}

再次,生成的XML(缩小到相关数据)。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
...
<element-list>
    <item name="activated_date"><value>2012-03-29 11:34:14.323</value></item>
    <item name="some_null_value"><value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/></item>
</element-list>
...

真的,我可以使用第二个,因为它可以解决我的问题。我只是想用这个作为学习经验,看看JAXB使用注释是否允许将其弯曲到我正在寻找的东西而不必在item标签下添加额外的值标签,这样我就可以支持null值。现在,当它在第一个例子中解组时,我最终得到空字符串而不是null。在第二个例子中,我得到了我期待的空值。

仅供参考:我目前正在使用Jersey 1.11

2 个答案:

答案 0 :(得分:2)

注意:我是EclipseLink JAXB (MOXy)主管,是JAXB 2 (JSR-222)专家组的成员。

您可以使用MOXy的@XmlNullPolicy扩展名来映射此用例:

<强> RestMapElements

package forum10415075;

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;

@XmlType(name="element")
public class RestMapElements {

  @XmlAttribute(name="name")
  public String key;

  @XmlValue
  @XmlNullPolicy(nullRepresentationForXml=XmlMarshalNullRepresentation.XSI_NIL)
  public String value;

}

<强>根

package forum10415075;

import java.util.*;
import javax.xml.bind.annotation.*;

@XmlRootElement
public class Root {

    @XmlElementWrapper(name="element-list")
    @XmlElement(name="item")
    public List<RestMapElements> items = new ArrayList<RestMapElements>();

}

<强> jaxb.properties

要将MOXy用作JAXB(JSR-222)提供程序,您需要在与域模型相同的程序包中添加名为jaxb.properties的文件,其中包含以下内容:

javax.xml.bind.context.factory = org.eclipse.persistence.jaxb.JAXBContextFactory

<强>演示

package forum10415075;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum10415075/input.xml");
        Root root = (Root) unmarshaller.unmarshal(xml);

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

}

<强> input.xml中/输出

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <element-list>
      <item name="activated_date">2012-03-29 11:34:14.323</item>
      <item name="some_null_value" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
   </element-list>
</root>

注意

如果您在GlassFish 3.1.2中使用Jersey,则MOXy或WebLogic 12.1.1已包含在内:

答案 1 :(得分:0)

我看到了你的问题。只有将您item(或其他)中的相应xsi:nil="true"条目设置为RestMapElements,才会生成ArrayList null元素,从而丢失该属性。我认为没有太多解决方案。

一种选择是使用您帖子开头的编组并使用以下内容解组:

如果您正在做这样的事情:

@XmlElementWrapper(name="element-list")
@XmlElement(name="item")
public ArrayList<RestMapElements> list;

您可以使用XmlAdapter检查value是否为空String,如果是null则设置为@XmlElementWrapper(name="element-list") @XmlElement(name="item") @XmlJavaTypeAdapter(ItemAdapter.class) public ArrayList<RestMapElements> list;

ItemAdapter

public class ItemAdapter extends XmlAdapter<RestMapElements, RestMapElements> { @Override public RestMapElements unmarshal(RestMapElements v) throws Exception { if (v.value.equals("")) v.value = null; return v; } }

xsi:nil="true"

虽然这仍然是不优雅的imho。 如果您想生成正确的item {{1}}元素,这显然不是您想要的。

祝你好运。