为啥 GSON 使用字段而不是 getter/setter?
Posted
技术标签:
【中文标题】为啥 GSON 使用字段而不是 getter/setter?【英文标题】:Why does GSON use fields and not getters/setters?为什么 GSON 使用字段而不是 getter/setter? 【发布时间】:2011-09-06 09:43:12 【问题描述】:为什么 GSON 使用 ONLY 字段(私有、公共、受保护)? 有没有办法告诉 GSON 只使用 getter 和 setter?
【问题讨论】:
【参考方案1】:可以将 Gson 修补到 use getters。
【讨论】:
我希望能够指定哪些变量应该使用getter和setter【参考方案2】:有没有办法告诉 GSON 只使用 getter 和 setter?
还没有。
来自the design doc:
[T]这里也有很好的论据来支持属性。我们打算在后一个版本中增强 Gson 以支持属性作为指示 Json 字段的替代映射。目前,Gson 是基于字段的。
【讨论】:
关于 Gson 对 getter 和 setter 的支持,来自邮件列表的最新更新是“[t] 他将这种功能纳入 Gson 的前景相当低......”groups.google.com/forum/#!topic/google-gson/4G6Lv9PghUY 我认为不应该使用 getter 和 setter,Chris Shaffer 在这个答案中解释得很好。 编写一个自定义的序列化器/反序列化器,这样你就可以使用任何你想将值写回你的类的方法。 这个答案很老了,*** 确实需要一些“垃圾收集器”来获得这样的答案。 @jb 不。答案仍然有效。【参考方案3】:这在我们的应用程序中如何工作的模糊概述是,我们有很多 TypeAdapter
实现 - 一些用于特定的类值对象,一些用于我们知道 JavaBeans 逻辑可以工作的 bean 样式对象。然后,在创建 Gson
对象之前,我们将所有这些都加到 GsonBuilder
上。
不幸的是,GSON 在处理Object[]
之类的类型方面确实很糟糕。当我们尝试创建一个 JSON 对象来表示方法参数时,我们经常看到这一点。解决方法是制作反映方法的自定义 TypeAdapter
实例。 (这确实意味着您最终要为每个您打算调用的方法使用一个 Gson
实例......)
【讨论】:
您将如何明智地处理将任何内容反序列化为 Object?为了反序列化,你想如何猜测它是什么? 对于对象,或一般多态的东西,它们可能有一个属性记录,适配器最初对其进行了序列化。但从记忆中,我认为即使是像 "a",2,"b" 这样明显的东西也没有反序列化为 Object[]。【参考方案4】:一般来说,当您序列化/反序列化对象时,您这样做是为了得到对象状态的精确副本;因此,您通常希望规避 OO 设计中通常需要的封装。如果您不规避封装,则可能无法最终得到一个在反序列化后具有与序列化之前完全相同的状态的对象。此外,请考虑您不想为特定属性提供 setter 的情况。如果您正在使用 getter 和 setter,序列化/反序列化应该如何处理?
【讨论】:
我们想提供给外部世界的“计算字段”怎么样?以您的想法,我应该在每次更新我的 POJO 字段时创建一个字段并更新该字段?呃…… @Frédéric - 我真的只是指出了使用属性获取器和设置器进行序列化所带来的困难;计算的属性也会引入它们自己的问题。例如,如果你给某人一个序列化对象,然后他们更新计算属性的值并将其传回给你,应用程序应该如何处理反序列化?假装属性没有更新或抛出异常?此外,如果他们更新计算属性所基于的属性,则对象状态实际上是无效的,并且读取该属性的值是完全错误的。 我同意@Frédéric;有一些边缘情况值得使用属性副字段。我刚刚遇到一个对象,我在一个对象上有一个字节数组,我想排除它,而是返回一个字符串。现在我要通过 DTO 调整对象了。 计算/派生字段应标记为transient
,因此它们不会被序列化,并应请求重新计算。
如果用例是 Java 到 Java 的序列化,这很好,但一个很常见的用例是通过 REST api 调用公开 Java 对象,在这种情况下,在 Java 端我们不这样做'不需要两种方式完美的序列化,更多时候我们想要隐藏字段并序列化(如果/需要时反序列化)特定的,通常是运行时计算的属性。以上是关于为啥 GSON 使用字段而不是 getter/setter?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Gson/Jackson 和 Spring Boot 重新创建没有字段属性的 DTO 类,而不是使其为空
为啥 Kotlin 数据类可以在 Gson 的不可空字段中包含空值?