1

我有一些 jaxb 对象使用具有值的容器对象建模元数据结构,这可能是另一个容器对象或只是一个简单的对象(例如字符串)。

@XmlRootElement(name = "value")
public class Value 
{

    protected SimpleType type;
    protected Container container;

    @XmlElement
    public SimpleType getType()
    {
        return type;
    }

    public void setType(SimpleType type)
    {
        this.type = type;
    }

    @XmlInverseReference(mappedBy="value")
    @XmlElement
    public Container getContainer()
    {
        return container;
    }

    public void setContainer(Container container)
    {
        this.container = container;
    }
}

@XmlRootElement(name = "container")
public class Container 
{
    protected Value value;

    @XmlElement
    public Value getValue()
    {
        return value;
    }

    public void setValue(Value value)
    {
        this.value = value;
    }
}

@XmlRootElement(name = "type")
@XmlEnum
public enum SimpleType
{
        @XmlEnumValue("String")STRING,
        @XmlEnumValue("Boolean")BOOLEAN,
....etc.
}

XML 看起来不错,但 JSON 最终具有重复的“容器”属性。

        <container>
          <value>
            <container>
              <value>
                <type>String</type>
              </value>
            </container>
          </value>
        </container>

            "container": {
              "value": {
                "container": {
                  "container": {
                    "value": {
                      "type": "STRING"
                    }
                  }
                }
              }
            }

知道为什么会有这种差异吗?

4

2 回答 2

0

注意: 我是EclipseLink JAXB (MOXy)负责人,也是JAXB (JSR-222)专家组的成员。

由于您的模型中有 MOXy 的@XmlInverseReference注释,您可能会对它如何应用于 JSON 案例感兴趣。

输入.xml

从您的问题中我可以看出,如果您在 and 之间具有双向关系,则 XML 表示应如下Container所示Value

<?xml version="1.0" encoding="UTF-8"?>
<container>
    <value>
       <type>String</type>
    </value>
</container>

领域模型

下面是如何映射您的域模型。我已经指定@XmlAccessorType(XmlAccessType.FIELD)并删除了访问器方法以使示例更短。

容器

package forum10706457;

import javax.xml.bind.annotation.*;

@XmlRootElement(name = "container")
@XmlAccessorType(XmlAccessType.FIELD)
public class Container 
{
    protected Value value;

}

价值

package forum10706457;

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

@XmlAccessorType(XmlAccessType.FIELD)
public class Value 
{

    protected SimpleType type;

    @XmlInverseReference(mappedBy="value")
    protected Container container;

}

简单类型

package forum10706457;

import javax.xml.bind.annotation.*;

@XmlEnum
public enum SimpleType
{
        @XmlEnumValue("String")STRING,
        @XmlEnumValue("Boolean")BOOLEAN,
}

jaxb.properties

注解是 MOXy 扩展,因此@XmlInverseReference您需要在与域模型相同的包中添加一个名为 jaxb.properties 的文件,并使用以下条目将 MOXy 指定为 JAXB 提供程序。

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

演示

下面的代码演示了如何加载 XML 文档,然后将生成的对象编组为 JSON。检查是否填充了双向关系。

package forum10706457;

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

public class Demo {

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

        File xml = new File("src/forum10706457/input.xml");
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Container container = (Container) unmarshaller.unmarshal(xml);

        System.out.println(container == container.value.container);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty("eclipselink.media-type", "application/json");
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(container, System.out);
    }

}

输出

下面是运行演示代码的输出。请注意@XmlEnumValue("String")STRING在 JSON 表示中是如何利用的。

true
{
   "container" : {
      "value" : {
         "type" : "String"
      }
   }
}

了解更多信息

于 2012-05-30T09:56:40.163 回答
0

这是因为 和 之间的循环Value依赖Container

UPD。请参阅JAXB 将循环引用映射到 XML

UPD2。请参阅JsonBackReferenceJsonManagedReference

于 2012-05-22T17:24:21.283 回答