【问题标题】:Converting Json object to hashmap?将 Json 对象转换为哈希图?
【发布时间】:2018-11-04 23:17:56
【问题描述】:

我有一个字符串对象,表示为网络任务返回的 json 对象。我需要将其转换为 Map(或 HashMap)。我一直在使用gson,但它一直不成功。这是json字符串(请原谅缩进,因为我必须手动添加换行符):

{
"plans":{
"Ankle Recovery":{
"StartDate":"09/24/2018",
"Progress":0.6666666666666666,
"Tasks":[
        {
            "date":"10/16/2018",
            "amount":200,
            "task":"ice ankle for 30 min",
            "completed":true,
            "requirementType":"steps"},
            {
                "date":"10/17/2018",
                "amount":200,
                "task":"ice ankle for 30 min",
                "completed":true,
                "requirementType":"steps"
            },
            {
                "date":"10/18/2018",
                "amount":200,
                "task":"ice ankle for 30 min",
                "completed":false,
                "requirementType":"steps"
            }
],
"Username":"email@site.com",
"Doctor":"Mike Michaels",
"EndDate":"12/24/2018"}},
"status":true
}

这是我用来进行转换的代码:

private Map<String, String> plans;
plans = new Gson().fromJson(result, new TypeToken<Map<String, String>>() {}.getType());

既没有也没有奏效。我在 Stack Overflow 上尝试了一些不同的解决方案,但到目前为止都没有成功。

我也抛出了一个我不太明白的异常:

 com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 11

(第 11 列就在“AnkleRecovery”中的第一个引号之前)

如果可能的话,我想使用简单的 gson 来完成这项工作。但我对替代解决方案持开放态度。

【问题讨论】:

  • 部分问题是,您的 JSON 不是Map&lt;String, String&gt; 的格式,它还有一个值列表。就个人而言,我会设计一个反映结构的 POJO,但这就是我。可以试试Map&lt;String, Object&gt; 吗?
  • 另外,您发布的 JSON 无效 - "Ankle Recovery"{ 是错误的 - 一旦我更正了,我可以将其解析为 Map&lt;String, Object&gt;
  • @MadProgrammer 你做了什么来纠正 JSON?
  • "Ankle Recovery"{ 必须是 "Ankle Recovery": { - 我经常做的第一件事就是将文本放入 JSON 格式化程序/验证器;)
  • @MadProgrammer 我明白了。另一个问题——当你拿到你的地图时,你能看到什么键?我只有计划和状态。我也需要嵌套值(“踝关节恢复”是我目前感兴趣的)。我怎样才能收集到这些

标签: java json hashmap gson


【解决方案1】:

您发布的 JSON 无效,第 3 行:

"Ankle Recovery" : {
//              / \
//  this is what you are missing

此工具将帮助您验证 JSON 结构并对其进行格式化:https://jsonlint.com/


现在到实际问题。您的 JSON 具有以下结构:

{
    "plans": Object,
    "status": Boolean,
}

这些都不是字符串(object != string, boolean != string)。
这样的结构不能映射到Map&lt;String, String&gt;,因为这要求值是一个字符串。

您将需要创建多个 POJO 来定义您的结构,然后映射到这些,例如:

class Project {
    public Map<String,Plan> plans;
    public Boolean status;
}

class Plan {
    public String StartDate;
    public Double Progress;
    public List<Task> tasks;
    ...
}

class Task {
    ...
}

【讨论】:

  • “你需要创建 ...” 可以说,你没有“必须”这样做,但如果结构稳定,你可以只需使用Map&lt;String, Object&gt;,但这需要更多的反省来解码结果......只是说;)
  • @MadProgrammer 正确,从技术上讲,您不必这样做,但是除了将其编码回 JSON 之外,这样的结构对任何东西都没有用,使用它将是 PITA,并且代码将很快成为大混乱。所以,是的,在现实世界中,你有点“不得不”。
  • 我不同意这是一个“混乱”,但即使在“真实”世界中,有时,为了获得单个属性而必须创建一堆 POJO 会更痛苦- 但每个案件都需要根据自己的优点来确定。以防万一,上面的示例使用 Ankle Recovery 作为键 - 坦率地说,这是键的腹部名称 - 并且可能表示键不稳定
  • 不能不同意这一点。此外,并非总是需要键入所有子对象,例如如果您只会将结构阅读到一定深度。我看到 Ankle Recovery 不是一个稳定的键,因为它看起来像一个计划名称,因此是 Map&lt;String, Plan&gt; 结构,其中 String 是计划名称。
【解决方案2】:

免责声明...

如果可能的话,我总是会研究使用一个或多个可用于表示数据结构的 POJO。

如果没有更多信息,就不可能知道像 Ankle Recovery 这样的键是否稳定,或者它们是否会改变。

“A”可能的解决方案

一般来说,JSON 是键/值对的形式,其中值可能是另一个 JSON 对象、数组或其他值的列表,因此您“可以”直接处理该结构,例如...

String text = "{\n"
        + "  \"plans\":{\n"
        + "    \"Ankle Recovery\":{\n"
        + "      \"StartDate\":\"09/24/2018\",\n"
        + "      \"Progress\":0.6666666666666666,\n"
        + "      \"Tasks\":[\n"
        + "        {\n"
        + "          \"date\":\"10/16/2018\",\n"
        + "          \"amount\":200,\n"
        + "          \"task\":\"ice ankle for 30 min\",\n"
        + "          \"completed\":true,\n"
        + "          \"requirementType\":\"steps\"\n"
        + "        },\n"
        + "        {\n"
        + "          \"date\":\"10/17/2018\",\n"
        + "          \"amount\":200,\n"
        + "          \"task\":\"ice ankle for 30 min\",\n"
        + "          \"completed\":true,\n"
        + "          \"requirementType\":\"steps\"\n"
        + "        },\n"
        + "        {\n"
        + "          \"date\":\"10/18/2018\",\n"
        + "          \"amount\":200,\n"
        + "          \"task\":\"ice ankle for 30 min\",\n"
        + "          \"completed\":false,\n"
        + "          \"requirementType\":\"steps\"\n"
        + "        }\n"
        + "      ],\n"
        + "      \"Username\":\"email@site.com\",\n"
        + "      \"Doctor\":\"Mike Michaels\",\n"
        + "      \"EndDate\":\"12/24/2018\"\n"
        + "    }\n"
        + "  },\n"
        + "  \"status\":true\n"
        + "}";

Gson gson = new Gson();
Map<String, Object> fromJson = gson.fromJson(text, Map.class);
Map<String, Object> plans = (Map<String, Object>) fromJson.get("plans");
Map<String, Object> recovery = (Map<String, Object>) plans.get("Ankle Recovery");
List<Map<String, Object>> tasks = (List<Map<String, Object>>) recovery.get("Tasks");
for (Map<String, Object> taks : tasks) {
    for (Map.Entry<String, Object> entry : taks.entrySet()) {
        System.out.println(entry.getKey() + " = " + entry.getValue());
    }
}

现在,这将为您提供...的输出

date = 10/16/2018
amount = 200.0
task = ice ankle for 30 min
completed = true
requirementType = steps
date = 10/17/2018
amount = 200.0
task = ice ankle for 30 min
completed = true
requirementType = steps
date = 10/18/2018
amount = 200.0
task = ice ankle for 30 min
completed = false
requirementType = steps

说了这么多,您自己的解析可能会涉及更多,必须检查某些键是否存在并根据需要采取适当的措施

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-04
    • 2011-03-12
    • 1970-01-01
    • 1970-01-01
    • 2011-06-29
    • 1970-01-01
    相关资源
    最近更新 更多