【问题标题】:How to convert JSON String to Map如何将 JSON 字符串转换为地图
【发布时间】:2017-03-22 02:35:38
【问题描述】:

很抱歉重复了这个问题,但我的问题是其他的。 我有 JSON 解析器方法,我从 json-string 解析到映射。但是 json-string 也有一个 json-string 的值。类似的东西:

    {
   "status_code":"255",
   "data":"{\"user\":{\"idpolzovatel\":1,\"id_poluch_tip\":1,\"fio_polzovatel\":\"Andrew Artificial\",\"login\":\"imi\",\"parol\":\"698d51a19d8a121ce581499d7b701668\",\"key\":null,\"nachalnik\":1,\"buhgalter\":0,\"delopr\":1},\"token\":\"230047517dd122c8f8116a6fa591a704\"}",
   "message":"Successfull!"
}

所以,我的解析方法:

public Map<String, String> convertToMapFromJSON(String res){
    ObjectMapper objectMapper = new ObjectMapper();
    Map<String, String> response = new HashMap<String, String>();
    try {
        response = objectMapper.readValue(res, new TypeReference<Map<String, String>>);
        int t = 0;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return response;
}

我在客户端得到响应:

ResponseEntity<String> responseEntity = restTemplate.postForEntity(REST_SERVICE_URI + "/auth/", data, String.class);

得到身体

String res = responseEntity.getBody();//получаем тело запроса в формате JSON

然后使用那些方法:

Map<String, String> response = convertToMapFromJSON(res);

Map<String, String> data1 = convertToMapFromJSON(response.get("data"));

Map<String, String> userDetailes = convertToMapFromJSON(data1.get("user"));

但是,当我使用最后一种方法data1.get("user"); 时,我得到了异常:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to java.lang.String

好的,知道了。所以,data1.get("user") 不是字符串,它是linkedHashMap。所以,我可以这样做:

Map<String, String> userDetailes = data1.get("user");

?但后来我得到错误,IDE 说我,data1.get("user") 是一个字符串。

调试器截图:

那么,如何使用我的用户数据获取这个 LinkedHashMap?对不起我的英语不好。谢谢。

【问题讨论】:

  • 有时 SDE 有问题;尝试清理项目并重建...并尝试从命令行(maven 或 javac)构建,这样您就不会依赖 IDE 编译器
  • 使用真实的 JSON 有效负载和使用的库(杰克逊?)更新您的问题
  • 更新问题。是的,我用过 Jackson 库。

标签: java json parsing hashmap linkedhashmap


【解决方案1】:

看起来 ObjectMapper 已将字符串解码为 JSON 格式并为您解析。您可以添加一个新方法来解析 (data1.get("user")) 它返回一个 Map。

【讨论】:

    【解决方案2】:

    Java 对泛型应用类型擦除。它在编译时检查类型正确性,然后删除编译代码(ByteCode)中的通用签名。因此,运行时没有检查。

    查看这个与您的 JSON 库具有相同行为的示例:

    /** Returns a generic map which all keys are string but not values **/
    T <T extends Map> raw(Class<T> clazz) {
        Map object = new LinkedHashMap();
        object.put("string", "This is a String");
        object.put("map"   , new LinkedHashMap());
        return (T) object;
    }
    

    这是您的代码:

    /** codes you try to execute/write **/
    void withStringValues() {
        Map<String,String> object = raw(Map<String,String>.class);
        String string = object.get("string"); // Ok
        String map    = object.get("map");    // ClassCastException
        Map    map    = object.get("map");    // Doesn't compile
    }
    

    正如您所见,对raw 的调用被认为是有效的,因为编译后的代码不检查泛型。但它会从MapMap&lt;String,String&gt; 进行无效和隐式转换,这实际上不会在编译代码中发生。

    泛型被移除,是编译后的版本:

    void withTypeErasure() {
        Map object = raw(Map.class);
        String string = (String) object.get("string");
        String map    = (String) object.get("map");
    }
    

    如您所见,Java 编译器已删除所有泛型并添加了必要的强制转换。你可以在这里看到哪里出了问题。

    您的真实代码必须如下所示:

    void withRealValues() {
        Map<String,Object> object = raw(Map<String,Object>.class);
        String             string = (String) object.get("string"); // Ok
        Map<String,Object> map    = (Map) object.get("map");       // Ok
    }
    

    【讨论】:

    • 改变方法。添加 TypeReference 类。
    • 添加 TypeReference 不会因为泛型类型擦除而改变任何东西。有效的泛型签名是Map&lt;String, Object&gt; 或没有泛型只是Map
    • 感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    • 2011-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多