【问题标题】:GSON error in Play framework 1.2.5Play 框架 1.2.5 中的 GSON 错误
【发布时间】:2012-11-15 23:41:12
【问题描述】:

该错误似乎是一个递归错误,即 Company 要求 Worksheets 再次要求 Company,这......你得到了漂移。我已经为此搜索了互联网和堆栈溢出,我发现了错误发生的原因,但解决方案总是编写自己的解析器或使用 flexjson 或其他。我只是想知道是否有解决方案,因为游戏非常流行,而且人们肯定会在一次操作中获取帖子和 cmets,或者不是吗?

必须有解决方案,无需更换 json 解析器或编写自己的解析器。

公司.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;


    }

}

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

在我的控制器中,我只是运行这个:

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

如果没有工作表,这可以工作,但是一旦有工作表,它就会崩溃并显示一英里长的错误消息。这是它的顶部:

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)

【问题讨论】:

  • 您可以编写自己的 JsonSerializer(继承自 GSON 的 JsonSerializer)。在这种情况下,您不必自己“解析”JSON。仅在序列化程序中“排除”您不想要的字段。这里有一个例子:stackoverflow.com/questions/9040060/…

标签: java playframework stack-overflow playframework-1.x


【解决方案1】:

恕我直言,这不是错误,您的模型中有递归,并且框架无法真正自动知道它应该如何序列化模型。

我通常使用@Expose 注解来解决这个问题。将其添加到您希望在序列化 JSON 中显示的所有成员中,并创建一个辅助方法来执行以下操作:

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

您也可以按照评论中的建议实现 JsonSerializer 接口。

【讨论】:

  • 有没有办法告诉 Gson 只下降 1 级以防止无限循环? Rails 做的正是我所期望的,我的期望来自那里。在 CakePHP 中,您可以定义递归的深度。但是 Play 中没有类似的东西吗?我在这里并没有贬低任何东西,只是想找到一个解决方案,然后再做我自己的序列化程序等。
  • 据我所知这是不可能的。有关 Gson 的详细信息,您可以查看 google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/…
  • 我不喜欢为我的模型添加注释,因为这样你就被所有调用的排除模式困住了,所以我使用 flexjson.JSONSerializer。使用 flexjson,您可以使用“*”排除模式,以便您只传递与调用相关的 json 数据。
  • 关于玩 flexjson 的博客:lunatech-research.com/archives/2011/04/20/…
【解决方案2】:

another question 中,我找到了指向this class 的链接,这似乎很好地解决了循环引用问题(并且无需修改模型类)。

有关示例,请参阅链接问题的批准答案。

【讨论】:

    猜你喜欢
    • 2012-07-13
    • 2012-12-24
    • 2013-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-07
    • 1970-01-01
    相关资源
    最近更新 更多