如何使用 Google 的 Gson API 正确反序列化 JSON?
Posted
技术标签:
【中文标题】如何使用 Google 的 Gson API 正确反序列化 JSON?【英文标题】:How do I use Google's Gson API to deserialize JSON properly? 【发布时间】:2011-02-21 07:18:15 【问题描述】:简而言之,这是我想用JAVA解析的JSON对象的草图:
object1:
item1: //[String | Array | Object] ,
item2: // ...
//<> more items
object2: /* .. */
//<> more objects
这些是我为解析而创建的 POJO (为简洁起见,我将省略 import
语句):
(1)完整JSON对象的表示
public class JObjectContainer
private List<JObject> jObjects ;
public JObjectContainer()
//get & set methods
(2)嵌套对象的表示:
public class JObject
private String id ;
private List<JNode> jObjects ;
public JObject()
//get & set methods
(3)物品的表示:
public class JNode
private JsonElement item1 ;
private JsonElement item2 ;
//<> more item fields
public JNode()
//get & set methods
现在,创建一个 Gson 实例(FileReader
用于导入 jsonFile
),
Gson gson = new Gson() ;
JObjectContainer joc = gson.fromJson(jsonFile,JObjectContainer.class) ;
每当我尝试访问可解析对象时(例如通过ListIterator
),我都会得到一个NullPointerException
。然而,Gson 确实创建了一个我指定的类的对象,并且没有抛出任何后续错误。
我知道以前有人这样做过。那么,我错过了什么?
TIA
【问题讨论】:
【参考方案1】:这是不可能的。您需要修改 JSON 结构以将 object1
、object2
等表示为 array 的项目。现在它们是一个对象的属性,显然不知道其中有多少(否则您没有尝试将其映射为List
)。 Gson 很聪明,但不是 那么 聪明 :)
因此,作为一个基本示例,这个带有数组的 JSON 结构:
nodes:
[
item1: 'value1a', item2: 'value2a' ,
item1: 'value1b', item2: 'value2b' ,
item1: 'value1c', item2: 'value2c'
]
结合Java表示(不一定叫POJO,只叫javabean或模型对象或值对象)。
public class Container
private List<Node> nodes;
// +getter.
public class Node
private String item1;
private String item2;
// +getters.
还有这个 Gson 调用
Container container = new Gson().fromJson(json, Container.class);
应该可以。
更新:需要明确的是,您的 JSON 结构是问题所在,而不是您的 Java 对象结构。假设您的 Java 对象结构正是您想要的,那么您的 JSON 结构应该如下所示,以让 Gson 完成其工作:
jObjects:
[
id: 123, jObjects:
[
item1: 'value1a', item2: 'value2a' ,
item1: 'value1b', item2: 'value2b' ,
item1: 'value1c', item2: 'value2c'
/* etc... commaseparated */
]
,
id: 456, jObjects:
[
item1: 'value1d', item2: 'value2d' ,
item1: 'value1e', item2: 'value2e' ,
item1: 'value1f', item2: 'value2f'
/* etc... commaseparated */
]
/* etc... commaseparated */
]
只有JsonElement
属性应该替换为String
,因为它是无效的。
【讨论】:
您好,感谢您的回答!我打算维护标识符字符串(例如Object1
),以便能够正确解析 Container 类的内容,就像我在 javascript 中那样。你知道该怎么做吗?
如果这些标识符字符串与每个项目 (Node
) 相关联,而不是与容器 (nodes
) 相关联,那么您需要将其设为 Node
的属性。具有未知数量的属性和未知属性名称的 JS 对象根本不是一个好主意/做法。你需要把它们放在一个数组中,并给数组一个固定的名字。
这有点超出了完全使用 JSON 的目的。如果我不能在 JAVA 中镜像 JSON 的对象映射样式,我还不如编写自己的 API。 ;-) 我基本上是在尝试做与这个 ***.com/questions/2710137/…> 相同的事情,同时以某种方式保留标识符字符串。
Java bean 中也不能有数量不确定的属性。您链接的主题基本上显示和回答相同:使用数组属性。您的问题只是对基本 OO 原则的误解/误解,而不是 JSON/Java。
是的,我知道。您需要将这些项目分组到 JSON 端的 一个数组 中,使用 [
和 ]
事物来识别其开始和结束。只有这样您才能在List
中收集它们。再次检查我的答案和该主题中的代码示例。我认为This tutorial 也可能有用。【参考方案2】:
我认为 BalusC 为 GSon 的特定问题提供了很好的指导(通常是一对一的数据绑定);但万一您认为应该有更多的动态处理,您也可以考虑其他 JSON 处理包。许多包都有其他或替代的映射方式:与 Gson 相比,Json-lib、flexjson 和 Jackson 至少有添加。有些提供更松散的映射(您将事物的名称定义为类型),有些则实际支持多态类型(声明一个 Object 但实际上可以映射到已序列化的子类型)。
【讨论】:
您好,感谢您的回答。实际上,我不太清楚 GSON 内部是如何运作的,因此不太了解如何使用它。我现在改用 Rhino 的自定义解析,我认为这更方便。 Java 不像 JavaScript 那样简单地支持嵌套数据对象,所以没有真正的理由不使用 Rhino 来做这种事情。以上是关于如何使用 Google 的 Gson API 正确反序列化 JSON?的主要内容,如果未能解决你的问题,请参考以下文章
发布到我的 Django API 时:errorcom.google.gson.JsonParseException: 无法解析 json