Jackson 里 objectMapper.readValue() 如何转换泛型 List<E>

本文介绍了如何使用Jackson库的readValue方法将JSON字符串转换为Java对象。包括基本类型的转换及复杂类型的处理,例如处理泛型List的情况。通过示例代码展示了具体的实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Jackson (com.fasterxml.jackson) 的 readValue 方法可以将json字符串转换成指定的对象

普通用法
import com.fasterxml.jackson.databind.ObjectMapper;

class Abc {
	Long a;
	
    public Long getA() {
        return a;
    }
    public void setA(Long a) {
        this.a= a;
    }
}
private ObjectMapper objectMapper;
Abc abc = objectMapper.readValue("{\"a\": 1000396667}", Abc.class);
如果碰见泛型怎么办? 比方说 List<E>,使用new TypeReference<List<Abc>>() {}
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

private ObjectMapper objectMapper;
List<Abc> abc = objectMapper.readValue("[{\"a\": 1000396667}]", new TypeReference<List<Abc>>() {});
package com.xuetu.util; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import java.io.IOException; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Map; public class JsonToMapTypeHandler extends BaseTypeHandler<Map<String, Integer>> { private final ObjectMapper objectMapper = new ObjectMapper(); @Override public void setNonNullParameter(PreparedStatement ps, int i, Map<String, Integer> parameter, JdbcType jdbcType) { try { ps.setString(i, objectMapper.writeValueAsString(parameter)); } catch (JsonProcessingException | SQLException e) { throw new RuntimeException("JSON序列化失败", e); } } @Override public Map<String, Integer> getNullableResult(ResultSet rs, String columnName) throws SQLException { return parseJson(rs.getString(columnName)); } @Override public Map<String, Integer> getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return null; } @Override public Map<String, Integer> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return null; } private Map<String, Integer> parseJson(String jsonStr) { try { return objectMapper.readValue(jsonStr, new TypeReference<Map<String, Integer>>(){}); } catch (IOException e) { throw new RuntimeException("JSON解析失败", e); } } }模仿上面Map<String, Integer> 写一个List<String>的
05-13
<think>嗯,用户遇到了一个Java的ClassCastException错误,错误信息是LinkedHashMap无法转换为ChartBoxPlotDetailVO。这个问题通常发生在处理JSON反序列化的时候,特别是当使用集合时,比如List<ChartBoxPlotDetailVO>。可能的原因是类擦除导致Jackson无法正确推断出集合元素的类,从而默认使用LinkedHashMap代替目标类。 首先,我需要了解用户代码的结构。用户从chartBoxPlotVO获取了data数据,然后遍历每个元素,尝试将d.getList()的字符串转换为int[][]数组。这可能存在两个问题:一是原始数据中的list字段可能没有被正确反序列化为int[][],二是data集合本身可能在反序列化时没有正确指定类,导致元素被反序列化为LinkedHashMap而不是ChartBoxPlotDetailVO。 接下来,用户使用Arrays.toString(d.getList())将list转换为字符串,再使用ObjectMapper重新反序列化为int[][]。但如果在chartBoxPlotVO的data字段没有被正确类化,可能在第一次反序列化时,data的元素已经是LinkedHashMap,而不是ChartBoxPlotDetailVO实例,从而导致遍历时的类转换错误。 解决这个问题的方法包括:确保chartBoxPlotVO的data字段在反序列化时使用正确的类信息,例如为ObjectMapper配置JavaType,明确指定集合类和元素类。另外,检查ChartBoxPlotDetailVO中的list字段是否正确定义为int[][]类,避免类不匹配。 可能的步骤是:在反序列化chartBoxPlotVO的data字段时,使用TypeFactory构造正确的JavaType,指定List的元素类为ChartBoxPlotDetailVO。这样,ObjectMapper就能正确地将JSON数组转换为目标类的集合,避免元素被错误地反序列化为LinkedHashMap。同时,确保ChartBoxPlotDetailVO中的list字段类正确,或者在需要的地方进行适当的类转换。</think>让我们逐步分析并解决这个类转换异常问题: ### 错误根源分析 `ClassCastException: LinkedHashMap cannot be cast to ChartBoxPlotDetailVO` 表示: 1.集合反序列化时,Jackson因类擦除无法识别具体类 2. 实际反序列化得到的是`LinkedHashMap`而不是目标VO对象 3. 可能发生在`chartBoxPlotVO.getData()`的初始化阶段 ### 解决方案步骤 #### 第一步:显式定义集合类 在反序列化包含的集合时,需要明确指定类信息: ```java // 修改获取data的方式 JavaType dataType = objectMapper.getTypeFactory() .constructCollectionType(List.class, ChartBoxPlotDetailVO.class); List<ChartBoxPlotDetailVO> data = objectMapper.readValue(originalJson, dataType); chartBoxPlotVO.setData(data); ``` #### 第二步:验证VO结构 确保`ChartBoxPlotDetailVO`正确定义: ```java public static class ChartBoxPlotDetailVO { private int[][] list; // ✅ 必须是二维int数组 // 必须包含正确的getter/setter public int[][] getList() { return list; } public void setList(int[][] list) { this.list = list; } } ``` #### 第三步:优化现有转换逻辑 修改遍历处理代码,添加类验证: ```java data.forEach(d -> { // 添加类检查 if (!(d instanceof ChartBoxPlotDetailVO)) { throw new IllegalStateException("无效的数据类: " + d.getClass()); } ChartBoxPlotDetailVO detail = (ChartBoxPlotDetailVO) d; try { // 直接转换而不是重新序列化 if (detail.getList() instanceof String) { int[][] realArray = objectMapper.readValue((String)detail.getList(), int[][].class); detail.setList(realArray); } } catch (JsonProcessingException e) { throw new RuntimeException("数据转换失败: " + e.getMessage(), e); } }); ``` ### 关键改进点 1.明确化:使用`constructCollectionType`确保集合元素正确反序列化 2. 防御性编程:添加`instanceof`检查确保类安全 3. 数据验证:处理可能的字符串到数组的转换场景 4. 异常处理:提供更清晰的错误信息定位问题 ### 补充建议 1. 使用`@JsonTypeInfo`注解(如果需要多态处理) 2. 在VO类中添加`@JsonIgnoreProperties(ignoreUnknown = true)`避免未知属性导致的错误 3. 使用单元测试验证JSON反序列化过程: ```java @Test void testDeserialization() throws Exception { String json = "{\"list\":[[1,2],[3,4]]}"; ChartBoxPlotDetailVO vo = objectMapper.readValue(json, ChartBoxPlotDetailVO.class); assertNotNull(vo.getList()); assertEquals(2, vo.getList().length); } ``` 通过以上步骤,可以系统性地解决类转换问题并建立更健壮的数据处理机制。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值