【问题标题】:Jersey Jackson duplicate JSON container attribute泽西杰克逊重复 JSON 容器属性
【发布时间】:2012-05-22 16:49:40
【问题描述】:

我有一些 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"
                    }
                  }
                }
              }
            }

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

【问题讨论】:

    标签: json jersey jackson


    【解决方案1】:

    这是因为ValueContainer之间的循环依赖

    UPD。见JAXB Mapping cyclic references to XML

    UPD2。见JsonBackReferenceJsonManagedReference

    【讨论】:

    • 我用@XmlInverseReference 更新了我的示例,但它似乎没有影响 json。
    【解决方案2】:

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

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

    input.xml

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

    <?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;
    
    }
    

    SimpleType

    package forum10706457;
    
    import javax.xml.bind.annotation.*;
    
    @XmlEnum
    public enum SimpleType
    {
            @XmlEnumValue("String")STRING,
            @XmlEnumValue("Boolean")BOOLEAN,
    }
    

    jaxb.properties

    @XmlInverseReference 注释是 MOXy 扩展,因此您需要在与域模型相同的包中添加一个名为 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"
          }
       }
    }
    

    更多信息

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-19
      • 2012-06-07
      • 2013-03-02
      相关资源
      最近更新 更多