【问题标题】:How do I figure out what fields to mark as transient when tryhing to use Gson's toJson method?尝试使用 Gson toJson 方法时,如何确定将哪些字段标记为瞬态?
【发布时间】:2017-11-29 19:24:17
【问题描述】:

我使用的是 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)

根据其他答案,如果我将导致此问题的循环引用标记为“瞬态”,这应该会消失,但我如何以编程方式解决这个问题?我已经查看了有问题的对象,通过代码检查循环引用是什么对我来说并不明显。

【问题讨论】:

    标签: java json serialization gson transient


    【解决方案1】:

    根据 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 序列化/反序列化并遇到一个我之前没有序列化的对象时,我会首先为它编写一个单元测试,以确保序列化和反序列化按我期望的方式工作,然后再将其放入生产代码.

    【讨论】:

    • 也许是因为我是 GSON 新手,但我不明白如何根据您的回答确定哪个字段是瞬态的。 “反复试验”是我一直在做的事情,但它并没有真正引导我到任何地方。
    • 如果一个字段不能被序列化,它需要是瞬态的。通常,这比具有几个数据值的简单对象(例如您的安全上下文示例)更复杂。
    猜你喜欢
    • 2015-02-06
    • 2011-07-07
    • 1970-01-01
    • 2020-06-22
    • 1970-01-01
    • 1970-01-01
    • 2015-12-25
    • 2013-04-20
    • 2022-01-15
    相关资源
    最近更新 更多