简体   繁体   English

Play框架1.2.5中的GSON错误

[英]GSON error in Play framework 1.2.5

The bug seems to be a recursion bug, that Company asks for Worksheets which asks for Company again, which .... you get the drift. 该错误似乎是一个递归错误,公司要求工作表,而工作表又要求公司,.... I have searched the internet and stack overflow for this, I found out why the error happens, but the solution is always write your own parser or use flexjson or some other. 我已经在互联网上搜索并发现堆栈溢出,我发现了为什么会发生错误,但是解决方案始终是编写自己的解析器或使用flexjson或其他方法。 I just want to know if there is a solution to this, there has to be since play is quite popular and surely people are fetching Posts and comments in one operation, or aren't they ? 我只想知道是否有解决方案,所以必须这样做,因为游戏很受欢迎,而且人们肯定会在一个操作中获取帖子和评论,不是吗?

There has to be a solution to this, without swapping out json parsers or writing your own. 必须有一个解决方案,而无需换出json解析器或编写自己的解析器。

Company.java 公司.java

package models;

import java.util.*;
import javax.persistence.*;

import play.db.jpa.*;

@Entity
public class Company extends Model {
    public String name;
    public String address;
    public String city;
    public String zipcode;
    public String country;
    public String phonenumber;
    public String website;
    public String footer;
    public String maincontactperson;
    public String email;
    public String password;
    public Blob logo;
    @OneToMany(mappedBy = "company", cascade = CascadeType.ALL, orphanRemoval = true, fetch=FetchType.EAGER)
    public List<Worksheet> worksheets;


    }

}

and

Worksheet.java 工作表

package models;

import java.util.*;
import javax.persistence.*;

import play.db.jpa.*;

@Entity
public class Worksheet extends Model {
    public String contactname;
    public String name;
    public String address;
    public String phonenumber;
    public String city;
    public String email;
    public String partnumber;
    @Lob
    public String partdescription;
    public String password;
    public Date due_date;
    public Date in_date;
    @Lob
    public String notes;
    @ManyToOne(cascade=CascadeType.ALL)
    public Company company;
...
}

In my controller, I just run this : 在我的控制器中,我只运行以下命令:

List<Company> companies = Company.FindAll();
renderJSON(companies);

This works if there are no worksheets, but once there is a worksheet, it crashes with a mile long error message. 如果没有工作表,这将起作用,但是一旦有了工作表,它就会崩溃并显示一英里长的错误消息。 Here is the top of it : 这是它的顶部:

00:31:02,623 ERROR ~ 

@6cbn7gi1o
Internal Server Error (500) for request POST /companies/login

Execution exception
InvocationTargetException occured : null

play.exceptions.JavaExecutionException
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:239)
    at Invocation.HTTP Request(Play!)
Caused by: java.lang.reflect.InvocationTargetException
    at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:557)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:508)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:484)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:479)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:161)
    ... 1 more
Caused by: java.lang.StackOverflowError
    at java.util.Date.getTimeImpl(Date.java:870)
    at java.util.Date.getTime(Date.java:866)
    at java.sql.Timestamp.getTime(Timestamp.java:126)
    at java.util.Calendar.setTime(Calendar.java:1076)
    at java.text.SimpleDateFormat.format(SimpleDateFormat.java:875)
    at java.text.SimpleDateFormat.format(SimpleDateFormat.java:868)
    at java.text.DateFormat.format(DateFormat.java:316)
    at com.google.gson.internal.bind.DateTypeAdapter.write(DateTypeAdapter.java:90)
    at com.google.gson.internal.bind.DateTypeAdapter.write(DateTypeAdapter.java:41)
    at com.google.gson.internal.bind.TypeAdapters$22$1.write(TypeAdapters.java:522)
    at com.google.gson.internal.bind.TypeAdapters$22$1.write(TypeAdapters.java:515)
....

    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:879)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)

IMHO this isn't a bug, you have a recursion in your model and the framework can't really know automatically how it should serialize the model. 恕我直言,这不是一个错误,您在模型中有一个递归,并且框架不能真正自动地知道它应该如何序列化模型。

I usually solve this with the @Expose annotation. 我通常使用@Expose注释解决此问题。 Add it to all the members you want to show up in your serialized JSON and create a helper method that does something like this: 将其添加到要显示在序列化JSON中的所有成员,并创建一个执行以下操作的辅助方法:

    Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
    String json = gson.toJson(your_model_instance);

Optionally you can also implement the JsonSerializer interface as suggested in the comment. (可选)您也可以按照注释中的建议实现JsonSerializer接口。

In another question , I found a link to this class , which seems to solve the circular reference problem nicely (and without modification of the model classes). 另一个问题中 ,我找到了指向该类的链接, 链接似乎可以很好地解决循环引用问题(并且无需修改模型类)。

See the approved answer to the linked question for an example. 有关示例,请参阅链接问题的批准答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM