Jackson convertValue()在Kotlin reified类型参数下失效,返回LinkedHashMap
问题核心成因
该问题由两层机制叠加触发:
- 泛型场景下的类型推导失效:在
fromMapReified方法内部调用JSON_MAPPER.convertValue(map)时,未给该Jackson Kotlin扩展方法显式传递目标类型参数。由于该调用处于泛型方法内部,编译器无法将外层方法返回值List<T>的类型信息自动传递给内层的convertValue调用。当Jackson拿不到明确的目标转换类型时,就会走通用兜底逻辑:将传入的Map结构按默认反序列化规则转成LinkedHashMap,最终返回一个装载LinkedHashMap的List,完全不会匹配预期的Money类型。 - 非泛型的
fromMap方法运行正常的原因在于:该方法的返回值为硬编码的List<Money>,编译器解析内部的convertValue调用时,可直接匹配固定返回类型推导出目标POJO类型,能正确完成Map到Money的转换,不会触发兜底逻辑。 - 关于reified类型参数的传递判断完全准确:虽然
reified T会在方法调用点保留类型信息,但这些信息仅存在于fromMapReified方法本身的上下文内,不会自动穿透到内部调用的convertValue方法上,需要手动将这些信息传递过去。
修复方案
核心思路为主动将构造完成的List<T>类型信息传给Jackson的转换方法,不依赖隐式的返回值类型推导,两种可直接运行的实现写法:
- 借助Jackson类型工厂显式构造集合类型
private inline fun <reified T> fromMapReified(map: List<Map<String, String>>) : List<T> { // 构造List<T>对应的完整JavaType,明确指定目标转换类型 val targetListType = JSON_MAPPER.typeFactory.constructCollectionType( List::class.java, T::class.java ) return JSON_MAPPER.convertValue(map, targetListType) } - 调用Jackson Kotlin的reified扩展时显式指定完整泛型参数
private inline fun <reified T> fromMapReified(map: List<Map<String, String>>) : List<T> { // 为convertValue显式传入List<T>的泛型实参,让内联生成的字节码携带正确的TypeReference return JSON_MAPPER.convertValue<List<T>>(map) }
两种写法均可让Jackson获取明确的目标类型,正确将Map结构转换为对应的Money实例,原有测试断言即可正常通过。
内容的提问来源于stack exchange,提问作者Michael Böckling
相关产品推荐
相关产品推荐

