You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

访问Map条目时遭遇ClassCastException问题求助

问题原因与解决方法

核心原因

你的JSON里"b"对应的值是嵌套JSON对象{"bb": "b1"},Jackson在解析JSON时,默认会把JSON对象转换成LinkedHashMap(实现了Map接口),而不是字符串。你声明的Map<String, String>是泛型限制为字符串值的Map,但实际b的value是Map类型,运行时强转就会抛出ClassCastException。

具体分析

  • 调用mapper.readValue(json, Map.class)时,未指定泛型类型,Jackson会将顶层JSON对象解析成LinkedHashMap<String, Object>:
    • "a"对应的值是字符串"a1",类型为String
    • "b"对应的值是嵌套JSON对象,被解析成LinkedHashMap<String, String>(内部"bb"对应"b1")
  • 你将这个Map赋值给Map<String, String> myMap属于未经检查的类型转换,编译器仅会给出警告但不报错;运行时调用myMap.get("b"),JVM尝试把实际的LinkedHashMap转成String,直接触发类型转换异常。

解决方案

方案1:将嵌套对象转为JSON字符串输出

如果需要把b的内容当作字符串输出,可通过Jackson将嵌套Map重新序列化为JSON字符串:

@Test
public void test1() throws Exception {
    String json = "{" + "\"a\": \"a1\"," + "\"b\": {" + "\"bb\": \"b1\"" + "}" + "}";

    final ObjectMapper mapper = new ObjectMapper();
    Map<String, Object> myMap = mapper.readValue(json, Map.class);

    String contentA = (String) myMap.get("a");
    System.out.println(contentA);
    
    // 把嵌套Map转成JSON字符串
    Object bValue = myMap.get("b");
    String contentB = mapper.writeValueAsString(bValue);
    System.out.println(contentB); // 输出 {"bb":"b1"}
}

方案2:使用正确的泛型Map

如果需要保留嵌套结构,直接声明匹配的泛型类型:

@Test
public void test1() throws Exception {
    String json = "{" + "\"a\": \"a1\"," + "\"b\": {" + "\"bb\": \"b1\"" + "}" + "}";

    final ObjectMapper mapper = new ObjectMapper();
    // 顶层Map的值可以是String或另一个Map
    Map<String, Object> myMap = mapper.readValue(json, Map.class);
    
    String contentA = (String) myMap.get("a");
    System.out.println(contentA);
    
    // 将b的值转为对应的Map
    Map<String, String> bMap = (Map<String, String>) myMap.get("b");
    System.out.println(bMap.get("bb")); // 输出 b1
}

也可以用更精确的泛型声明避免编译器警告:

Map<String, Object> myMap = mapper.readValue(json, new TypeReference<Map<String, Object>>() {});

方案3:使用实体类映射(推荐)

对于结构固定的JSON,创建对应实体类是最规范的做法,彻底避免类型转换问题:

// 顶层实体类
class Demo {
    private String a;
    private B b;
    
    // 生成getter、setter、toString方法
    public String getA() { return a; }
    public void setA(String a) { this.a = a; }
    public B getB() { return b; }
    public void setB(B b) { this.b = b; }
    @Override
    public String toString() { return "Demo{a='" + a + "', b=" + b + "}"; }
}

// 嵌套的B类
class B {
    private String bb;
    
    public String getBb() { return bb; }
    public void setBb(String bb) { this.bb = bb; }
    @Override
    public String toString() { return "B{bb='" + bb + "'}"; }
}

@Test
public void test1() throws Exception {
    String json = "{" + "\"a\": \"a1\"," + "\"b\": {" + "\"bb\": \"b1\"" + "}" + "}";

    final ObjectMapper mapper = new ObjectMapper();
    Demo demo = mapper.readValue(json, Demo.class);
    
    System.out.println(demo.getA()); // 输出 a1
    System.out.println(demo.getB().getBb()); // 输出 b1
}

内容的提问来源于stack exchange,提问作者Michael S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 14:46:23