Play Framework - JSON序列化循环引用(例如Files-> User,User-> Files) - >堆栈溢出

时间:2014-02-17 21:33:34

标签: json parsing exception playframework stack-overflow

我已经玩了几天玩游戏框架,但遇到了一个我无法解决的问题:假设你有一些“用户”和“文件”类。两者互相引用,并使用ebean(@ManyToOne,@ OneToMany)保存在数据库中。现在当用户返回JSON时,我得到一个stackoverflow错误。这是一个游戏中的错误还是我错过了什么?

@Entity
public class File extends Model {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    public Long id;

    @ManyToOne(cascade=CascadeType.ALL)
    public User author;
}

@Entity
public class User extends Model {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    public Long id;

    @OneToMany(mappedBy="author", cascade=CascadeType.ALL)
    public List<File> files;
}

import play.libs.Json;
public class Users extends Controller {
   public static Result getJSON() {
        List<User> users = new Model.Finder<String, User>(String.class, User.class).all();
        return ok(Json.toJson(users));
    }
 }

堆栈跟踪:

org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: 
    models.User["files"]->com.avaje.ebean.common.BeanList[0]->models.File["author"]->
    models.User["files"]->com.avaje.ebean.common.BeanList[0]->models.File["author"]->
    models.User["files"]->com.avaje.ebean.common.BeanList[0]->models.File["author"]->
    models.User["files"]->com.avaje.ebean.common.BeanList[0]->models.File["author"]->
    models.User["files"]->com.avaje.ebean.common.BeanList[0]->models.File["author"]->
    models.User["files"]->com.avaje.ebean.common.BeanList[0]->models.File["author"]->
    models.User["files"]->com.avaje.ebean.common.BeanList[0]->models.File["author"]->
    models.User["files"]->com.avaje.ebean.common.BeanList[0]->models.File["author"]->
    .
    .
    .
    ->models.User["files"])
    at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:164) ~[jackson-mapper-asl.jar:1.9.10]
    at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112) ~[jackson-mapper-asl.jar:1.9.10]
    at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446) ~[jackson-mapper-asl.jar:1.9.10]
    at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150) ~[jackson-mapper-asl.jar:1.9.10]
    at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112) ~[jackson-mapper-asl.jar:1.9.10]
    at org.codehaus.jackson.map.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:72) ~[jackson-mapper-asl.jar:1.9.10]
 java.lang.StackOverflowError: null
    at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.7.0_45]
    at java.lang.ClassLoader.defineClass(ClassLoader.java:800) ~[na:1.7.0_45]
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.7.0_45]
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449) ~[na:1.7.0_45]
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71) ~[na:1.7.0_45]
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361) ~[na:1.7.0_45]

1 个答案:

答案 0 :(得分:6)

好的,经过数小时的谷歌搜索我找到了解决方案: 有一个注释@JsonIgnore(从org.codehaus.jackson.annotate.JsonIgnore导入它),它告诉JSON方法忽略这个属性。

编辑:进一步深入研究,在JSON序列化期间处理循环引用的更清洁的解决方案是编写自定义的De-和Serializer。史蒂夫希尔的一篇非常好的文章可以在这里找到:http://dev.sghill.net/2012/04/how-do-i-write-jackson-json-serializer.html