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

如何让Json4s或其他Scala JSON库生成Java集合?

解决Json4s解析后Scala List转Java ArrayList的ClassCastException问题

问题背景

你在使用依赖Java集合(比如java.util.ArrayList)的Java库时,遇到了一个棘手的问题:因为输入JSON是动态结构的,你只能用Json4s的parse(json).extract[Map[String, Any]]来解析,结果调用Java库时抛出了java.lang.ClassCastException: scala.collection.immutable.$colon$colon cannot be cast to java.util.ArrayList异常。

问题根源

你的猜测完全正确:Json4s默认会把JSON数组(JArray)解析成Scala的不可变List(也就是scala.collection.immutable.List,运行时类型是scala.collection.immutable.$colon$colon),而Java库期望的是java.util.ArrayList这类Java集合类型,直接强制转换自然会失败。

解决方案

下面提供几种实用的解决思路,你可以根据自己的场景选择:

1. 手动转换Scala集合为Java集合

如果已经拿到了Map[String, Any],可以递归遍历这个Map,把所有Scala List转换成Java ArrayList。比如写一个工具方法:

import scala.jdk.CollectionConverters._
import java.util.ArrayList

def convertScalaCollectionsToJava(obj: Any): Any = obj match {
  case list: List[_] => new ArrayList(list.map(convertScalaCollectionsToJava).asJava)
  case map: Map[String, _] => map.mapValues(convertScalaCollectionsToJava).asJava
  case other => other
}

// 使用方式
val parsedMap = parse(json).extract[Map[String, Any]]
val javaFriendlyMap = convertScalaCollectionsToJava(parsedMap).asInstanceOf[java.util.Map[String, Any]]

这样处理后,所有Scala List都会被转换成ArrayList,Java库就能正常识别了。(注:Scala 2.13+推荐用scala.jdk.CollectionConverters,旧版本可以用scala.collection.JavaConverters)

2. 让Json4s直接解析为Java集合类型

如果不需要通用的Map[String, Any],可以定义一个更贴合Java库需求的case class,指定用Java集合类型:

import java.util.ArrayList
import org.json4s.DefaultFormats

// 根据你的JSON结构定义对应case class
case class ApiResponse(data: ArrayList[String], metadata: ArrayList[Map[String, String]])

implicit val formats = DefaultFormats
val response = parse(json).extract[ApiResponse]

Json4s会自动把JSON数组解析成ArrayList,直接传给Java库即可。

3. 自定义Json4s的提取器

如果必须用Map[String, Any],可以自定义一个提取器,让Json4s在解析数组时直接生成Java ArrayList:

import org.json4s._
import org.json4s.JsonAST._
import java.util.ArrayList

class JavaCollectionExtractors extends DefaultFormats {
  override def extract(jv: JValue, mf: Manifest[_]): Any = jv match {
    case JArray(arr) if mf.runtimeClass == classOf[ArrayList[_]] =>
      val list = new ArrayList[Any]()
      arr.foreach(item => list.add(extract(item, mf.typeArguments.head)))
      list
    case _ => super.extract(jv, mf)
  }
}

// 使用方式
implicit val formats = new JavaCollectionExtractors
val parsedMap = parse(json).extract[Map[String, ArrayList[Any]]]

这种方式能让Json4s直接生成Java ArrayList,避免后续转换步骤。

内容的提问来源于stack exchange,提问作者Tonny Tc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:33:25