Scala 2.12中如何获取classOf[Array[T]]?Jackson反序列化报错求助
Scala 2.12中Jackson泛型数组类型转换实现方案
这个需求完全可以实现,原代码报错的核心原因是Java类型擦除导致Jackson无法识别Array[T]的具体泛型类型,进而反序列化失败触发MatchError。以下是具体解决思路和修正后的代码:
关键问题分析
原代码中classOf[Array[T]]在运行时会被擦除为Array.class,Jackson无法得知要将JSON转换为哪种具体的样例类数组,只能默认转成Array[Any]或Array[LinkedHashMap]。当后续尝试将这些对象强转为你的样例类时,就会抛出MatchError。
解决方案步骤
引入Jackson Scala模块:原生Jackson对Scala样例类、泛型的支持不完善,必须添加专门的Scala模块依赖(以SBT为例):
libraryDependencies += "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.15.2" // 适配Scala 2.12的版本注册Scala模块到ObjectMapper:让Jackson能正确处理Scala的类型系统:
val objectMapper = new ObjectMapper().registerModule(DefaultScalaModule)用TypeReference保留泛型信息:替代
classOf[Array[T]],通过TypeReference传递完整的泛型类型,避免类型擦除问题。
修正后的代码(两种实现方式)
方式1:显式传入TypeReference
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.scala.DefaultScalaModule import com.fasterxml.jackson.core.`type`.TypeReference import java.io.File private val objectMapper = new ObjectMapper().registerModule(DefaultScalaModule) private def fromSeqToCastedSeq[T](files: Seq[File], typeRef: TypeReference[Array[T]]): Seq[T] = { files.flatMap { file => val maps = objectMapper.readValue(file, classOf[Map[String, Any]]) val sqlDefsStr = objectMapper.writeValueAsString(maps.get("sqlDefinitions")) objectMapper.readValue(sqlDefsStr, typeRef) } } // 调用示例(假设你的样例类为SqlDefA、SqlDefB) val sqlDefAType = new TypeReference[Array[SqlDefA]] {} val resultA: Seq[SqlDefA] = fromSeqToCastedSeq(files, sqlDefAType) val sqlDefBType = new TypeReference[Array[SqlDefB]] {} val resultB: Seq[SqlDefB] = fromSeqToCastedSeq(files, sqlDefBType)
方式2:用Scala TypeTag自动推导类型(更简洁)
利用Scala的TypeTag隐式传递类型信息,无需手动创建TypeReference:
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.scala.DefaultScalaModule import com.fasterxml.jackson.core.`type`.TypeReference import java.io.File import scala.reflect.runtime.universe._ private val objectMapper = new ObjectMapper().registerModule(DefaultScalaModule) private def fromSeqToCastedSeq[T: TypeTag](files: Seq[File]): Seq[T] = { val typeRef = new TypeReference[Array[T]] {} files.flatMap { file => val maps = objectMapper.readValue(file, classOf[Map[String, Any]]) val sqlDefsStr = objectMapper.writeValueAsString(maps.get("sqlDefinitions")) objectMapper.readValue(sqlDefsStr, typeRef) } } // 调用示例 val resultA: Seq[SqlDefA] = fromSeqToCastedSeq(files) val resultB: Seq[SqlDefB] = fromSeqToCastedSeq(files)
额外说明
- 确保你的样例类符合Jackson的序列化要求:无参构造函数(Scala样例类默认生成)、字段可访问(样例类字段默认是public的)。
- 如果JSON结构和样例类字段不匹配,可能需要添加Jackson注解(如
@JsonProperty)来映射字段名。
内容的提问来源于stack exchange,提问作者nariver1
相关产品推荐
相关产品推荐

