如何使用 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 结构以将 object1object2 等表示为 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?的主要内容,如果未能解决你的问题,请参考以下文章

Gson和fastJson的使用

发布到我的 Django API 时:errorcom.google.gson.JsonParseException: 无法解析 json

完全理解Gson:简单入门

Google Gson 使用简介

google 的 gson 序列化器使用

GSON常用API