2

我在两个对象之间有双向关系。我有一个使用 Jersey 1.17 和 Jackson 2.1.4 的 RESTful Web 服务。我还在使用 @JsonIdentityInfo 注释(显然是错误的方式!)来阻止 Json 进入无限循环。但是,生成的 Json 仍然是两个对象之间的无限循环。

第一个对象是:

@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@id")
public class Child {

    private long value;
    private Parent parent;

    public long getValue() {
        return this.value;
    }

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

    public Parent getParent() {
        return this.parent;
    }

    public void setParent(Parent parent) {
        this.parent = parent;
    }

}

第二个对象是:

@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@id")
public class Parent {

    private long value;
    private Set<Child> childs = new HashSet<Child>(0);

    public long getValue() {
        return this.value;
    }

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

    public Set<Child> getChilds() {
        return this.childs;
    }

    public void setChilds(Set<Child> childs) {
        this.childs = childs;
    }

}

这是生成 Json 的方法。

@GET
@Path("/test")
@Produces(MediaType.APPLICATION_JSON)
public Child getChild() {

    Child child = new Child();
    Parent parent = new Parent();
    child.setValue(1L);
    parent.setValue(2L);
    child.setParent(parent);
    Set<Child> childs = new HashSet<Child>(0);
    childs.add(child);
    parent.setChilds(childs);
    return child;

}

编辑:

生成的 Json 如下所示:

{"value":1,"parent":{"value":2,"childs":[{"value":1,"parent":{"value":2,"childs":[...

并且这 9 行在服务器的日志文件中一遍又一遍地重复......

at org.codehaus.jackson.map.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:86)
at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446)
at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150)
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446)
at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150)
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
at org.codehaus.jackson.map.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:72)
at org.codehaus.jackson.map.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:23)

web.xml 文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  id="WebApp_ID" version="2.5">
  <display-name>Jersey REST Service</display-name>
  <servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>com.sun.jersey.config.property.packages</param-name>
      <param-value>test</param-value>      
    </init-param>
    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/api/*</url-pattern>
  </servlet-mapping>
 </web-app> 
4

2 回答 2

5

您说您使用的是 Jackson 2.1.4,但堆栈跟踪显示 Jackson 的包以“ org.codehaus.jackson”开头,这是 Jackson 1.x 的基本包。Jackson 2.x 的基础包是“ com.fasterxml.jackson”。因此 Jersey 配置了 Jackson 1.x(很可能是 1.9.2,这是Jersey 1.17 中的默认值)。我的猜测是,您正在使用从 Jackson 2.x 导入的 Annotations 对代码进行注释,但 Jersey 使用的 Jackson 库不知道这些,因此无法序列化。

您的代码在 Jackson 2.3.0 中对我很有效。

于 2013-12-18T22:07:47.673 回答
3

对于字段之间的双向链接,您应该查看@JsonManagedReference@JsonBackReference注释。我认为@JsonIdentifyInfo 根本无法达到这种行为。

public class Parent {

private long value;
@JsonManagedReference private Set<Child> childs = new HashSet<Child>(0);

public long getValue() {
    return this.value;
}

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

public Set<Child> getChilds() {
    return this.childs;
}

public void setChilds(Set<Child> childs) {
    this.childs = childs;
}

}

…</p>

public class Child {

private long value;
@JsonBackReference private Parent parent;

public long getValue() {
    return this.value;
}

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

public Parent getParent() {
    return this.parent;
}

public void setParent(Parent parent) {
    this.parent = parent;
}

}

您可以在此处找到更多示例。

于 2013-03-14T13:07:10.757 回答