在尝试使用Gson的toJson方法时,如何确定要标记为瞬态的字段?

时间:2017-06-26 20:48:32

标签: java json serialization gson transient

我正在使用Gson 2.8.1。我有这个代码

        Object o = session.getSecurityContext();
        Gson gson = new Gson();
        String serialized = gson.toJson(o);

导致此堆栈溢出错误。

15:45:47,784 ERROR [io.undertow.request] (default task-58) UT005023: Exception handling request to /ebook/WEB-INF/views/registration/studentConfirm.jsp: java.lang.StackOverflowError
    at sun.util.locale.provider.DateFormatSymbolsProviderImpl.getInstance(DateFormatSymbolsProviderImpl.java:85)
    at java.text.DateFormatSymbols.getProviderInstance(DateFormatSymbols.java:359)
    at java.text.DateFormatSymbols.getInstance(DateFormatSymbols.java:335)
    at java.util.Calendar.getDisplayName(Calendar.java:2110)
    at java.text.SimpleDateFormat.subFormat(SimpleDateFormat.java:1125)
    at java.text.SimpleDateFormat.format(SimpleDateFormat.java:966)
    at java.text.SimpleDateFormat.format(SimpleDateFormat.java:936)
    at java.text.DateFormat.format(DateFormat.java:345)
    at com.google.gson.internal.bind.DateTypeAdapter.write(DateTypeAdapter.java:83)
    at com.google.gson.internal.bind.DateTypeAdapter.write(DateTypeAdapter.java:41)
    at com.google.gson.internal.bind.TypeAdapters$26$1.write(TypeAdapters.java:586)
    at com.google.gson.internal.bind.TypeAdapters$26$1.write(TypeAdapters.java:579)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:125)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243)
    at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:976)

根据其他答案,如果我将引起此问题的循环引用标记为" transient,"这应该会消失,但我如何以编程方式解决这个问题呢?我查看了有问题的对象,通过代码检查循环引用对我来说并不明显。

1 个答案:

答案 0 :(得分:0)

根据GSON用户指南(https://sites.google.com/site/gson/gson-user-guide),当字段不应序列化时,您将字段标记为 transient

理想情况下,您事先知道哪些引用是循环的,并且只是避免序列化它们。另一方面,您可能不知道这些信息,因此从不太复杂的部分构建复杂对象的某种方式有时是有益的。

例如,如果我尝试序列化复杂的Date对象,最好只添加如下构造函数:

public Date(double ms) {
  // create new Date from milliseconds from the epoch
}

然后,您将序列化Date对象,将其转换为毫秒并序列化double。您可以使用类型拦截器根据类型执行此类条件序列化。

自Java语言出现以来,序列化一直是个问题。你不能简单地将任何对象粘贴到一个序列化机制中,并且不幸的是,它会神奇地发挥作用。也就是说,许多对象与GSON协同工作,只要你稍微分解它们。

当所有其他方法都失败时,试验和错误(就像你刚刚看到的那样)也有效。当我使用GSON序列化/反序列化时,我遇到了一个我以前没有序列化的对象,我首先会为它编写一个单元测试,以确保序列化和反序列化按照我期望的方式工作,然后再将其放入生产代码中