【问题标题】:Parsing complex nested JSON data with Gson使用 Gson 解析复杂的嵌套 JSON 数据
【发布时间】:2015-05-31 15:19:46
【问题描述】:

我正在使用 Gson 来解析 JSON 字符串。我想使用容器类和嵌入式静态类将其转换为对象。在某种程度上这是可能的,但我想将stuff1stuff2的内容视为数组,例如stuff1是一个包含other_stuff1other_stuff2的数组。这样我就可以以如下方式引用该对象:object.integerobject.stuff1.get("other_stuff1").nameobject.stuff2.get("other_stuff3").more。 (对于最后一个,我可能有兴趣循环 more 以获取每个项目。

例如,在 PHP 中,我会使用这个:

<?php
    echo "<pre>";
    $object = json_decode(file_get_contents("THE JSON FILENAME"));
    foreach($object->stuff1 as $name=>$data) {
        echo $name . ":\n"; // other_stuff1 or other_stuff2
        echo $unlockable->description . "\n\n"; // Got lots of stuff or Got even more stuff.
    }
?>

我希望能够以类似的方式引用,将 JSON 加载到要动态使用的对象。

重要的是,虽然可以对 JSON 进行一定程度的更改,但元素的名称保持不变并且可以引用和检索。

我已经包含了 JSON,与我正在使用的非常相似,如下所示。

{
    "integer":"12345",
    "stuff1":{
        "other_stuff1":{
            "name":"a_name",
            "description":"Got lots of stuff.",
            "boolean":false
        },
        "other_stuff2":{
            "name":"another_name",
            "description":"Got even more stuff",
            "boolean":true
        }
    },
    "stuff2":{
        "other_stuff3":{
            "name":"a_name",
            "description":"Got even more stuff",
            "boolean":false,
            "more":{
                "option1":{
                    "name":"hello"
                },
                "option2":{
                    "name":"goodbye"
                }
            }
        },
    }
}

我已经阅读了许多参考指南和教程,但我找不到一种方法来解释我想要的方式。

如果有人能给我指点,我将不胜感激。我找不到任何教程考虑到 a) 我想要一个数组样式列表中的多个对象,可通过 ID 引用(如 other_stuff1other_stuff2),以及 b) 我也希望能够在不提供 ID 的情况下遍历项目。

【问题讨论】:

    标签: java json object nested gson


    【解决方案1】:

    您应该定义一个 Java 类,其中包含以您需要的键命名的字段。您可以使用 Maps(不是数组)来获取您描述的 .get("key") 行为。例如:

    class Container {
      private final int integer;
      private final HashMap<String, Stuff> stuff1;
      private final HashMap<String, Stuff> stuff2;
    }
    
    class Stuff {
      private final String name;
      private final String description;
      @SerializedName("boolean") private final boolean bool;
      private final HashMap<String, Option> more;
    }
    
    class Option {
      private final String name;
    }
    

    对于"boolean" 字段,您需要use a different variable name,因为boolean 是保留关键字。

    你可以这样做:

    Container c = gson.fromJson(jsonString, Container.class);
    for(Stuff s : c.getStuff1().values()) {
      System.out.println(s.getName());
    }
    

    【讨论】:

    • 将Container中的字段声明为Map而不是HashMap是否足够?
    • @ralfstx 快速测试表明,如果您指定Map,Gson 将构建com.google.gson.internal.LinkedTreeMap。还有一个LinkedHashTreeMap 有时可能会返回。最好明确说明您想要的类型(例如 HashMapLinkedHashMap 等),但如果您仅将 Map 指定为所需类型,Gson 将使用合理的默认值。
    • 这些地图实现在迭代时保持元素的原始顺序,这可能是需要的。 HashMapMap 接口的流行实现,但对于Container 类型的用户来说,这个实现是无关紧要的。
    • 我不确定你在做什么,但 OP 应该使用对他们有用的东西。使用 Map 将实现留给 Gson,这可能是不可取的。明确你的类型通常是个好主意。
    • 这绝对是完美的。在这一点上,似乎与 HashMap 保持一致是可行的方法,因为它对我来说是最容易使用的,但我可以肯定地说我已经能够使用你的代码并将它变成我正在寻找的东西.谢谢!
    猜你喜欢
    • 1970-01-01
    • 2013-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多