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

如何将Scala嵌套Map转换为Java嵌套util.Map适配Stripe Java API

问题:Scala中嵌套集合转换为Java集合适配Stripe API

我在Scala项目中集成Stripe,但Stripe只提供Java API。最初我用纯Java风格的代码创建会话,虽然能正常运行,但写法繁琐,有大量模板代码:

val params = new util.HashMap[String, AnyRef]
val paymentMethodTypes = new util.ArrayList[String]
paymentMethodTypes.add("card")
params.put("payment_method_types", paymentMethodTypes)
params.put("mode", "setup")
params.put("success_url", "https://test.app/success")
params.put("cancel_url", "https://test.app/cancel")
val session = Session.create(params)

我想改用更简洁的Scala Map[String, AnyRef]来实现,于是尝试了以下代码:

import scala.collection.JavaConverters._
val params2: Map[String, AnyRef] = Map(
 "payment_method_types" -> List("card"),
 "mode" -> "setup",
 "success_url" -> "https://test.app/success",
 "cancel_url" -> "https://test.app/cancel"
)
val session2 = Session.create(mapAsJavaMap[String, AnyRef](params2))

但发现mapAsJavaMap只能转换顶层的Map,无法处理嵌套的Scala集合(比如这里的List,或者更深层的Map)。请问有没有办法将包含嵌套Map和List的任意Scala Map转换为对应的Java等价集合?


解决方案:递归转换嵌套Scala集合到Java集合

默认的mapAsJavaMap确实只能处理顶层的Scala Map,嵌套的Scala List/Map还是会保持原类型,Stripe的Java API无法识别这些类型。要解决这个问题,我们需要编写一个递归转换函数,遍历集合中的每个元素,把所有嵌套的Scala集合都转换成对应的Java集合类型。

方法1:自定义递归转换工具类

这个工具类会递归处理所有嵌套的Scala Map和List,将它们分别转为Java的HashMap和ArrayList,非集合类型则直接保留:

import scala.collection.JavaConverters._
import java.util.{HashMap, ArrayList}

object StripeCollectionConverter {
  // 对外暴露的转换方法,处理顶层Scala Map
  def toJavaParams(scalaMap: Map[String, AnyRef]): java.util.Map[String, AnyRef] = {
    val javaMap = new HashMap[String, AnyRef]()
    scalaMap.foreach { case (key, value) =>
      javaMap.put(key, convertToJava(value))
    }
    javaMap
  }

  // 递归处理每个元素
  private def convertToJava(value: AnyRef): AnyRef = value match {
    // 处理Scala List,转为Java ArrayList
    case scalaList: List[_] =>
      val javaList = new ArrayList[AnyRef]()
      scalaList.foreach(item => javaList.add(convertToJava(item.asInstanceOf[AnyRef])))
      javaList
    // 处理嵌套的Scala Map,递归调用转换方法
    case scalaMap: Map[String, _] =>
      toJavaParams(scalaMap.asInstanceOf[Map[String, AnyRef]])
    // 非集合类型直接返回(比如字符串、数字等)
    case other => other
  }
}

使用示例

现在你可以用这个工具类来构建嵌套的Scala参数,然后一键转换为Stripe需要的Java集合:

val params2: Map[String, AnyRef] = Map(
  "payment_method_types" -> List("card", "ideal"), // 嵌套Scala List
  "mode" -> "setup",
  "success_url" -> "https://test.app/success",
  "cancel_url" -> "https://test.app/cancel",
  "metadata" -> Map("user_id" -> "123", "order_id" -> "456") // 嵌套Scala Map
)

// 转换为Java集合
val javaParams = StripeCollectionConverter.toJavaParams(params2)
// 调用Stripe API
val session2 = Session.create(javaParams)

方法2:Scala 2.13+ 简化版(用CollectionConverters)

如果你用的是Scala 2.13或更高版本,可以用官方推荐的scala.jdk.CollectionConverters替代旧的JavaConverters,代码会更简洁:

import scala.jdk.CollectionConverters._
import java.util.{HashMap, ArrayList}

object StripeCollectionConverter {
  def toJavaParams(scalaMap: Map[String, AnyRef]): java.util.Map[String, AnyRef] = {
    scalaMap.map { case (k, v) =>
      k -> convertToJava(v)
    }.asJava
  }

  private def convertToJava(value: AnyRef): AnyRef = value match {
    case list: List[_] => list.map(convertToJava).asJava
    case map: Map[String, _] => toJavaParams(map.asInstanceOf[Map[String, AnyRef]])
    case other => other
  }
}

注意事项

  • 递归的必要性:Stripe的API参数经常会有多层嵌套(比如metadata、line_items等),只有递归处理才能确保所有嵌套集合都被正确转换。
  • 类型扩展:如果你的参数里有其他Scala集合类型(比如Set),可以在模式匹配里添加对应的转换逻辑(比如转为Java HashSet)。
  • 版本兼容性:Scala 2.12及以下用JavaConverters,2.13+建议用CollectionConverters,前者已经被标记为过时。

这样你就能用简洁的Scala风格代码来构建Stripe参数,再也不用写繁琐的Java集合模板啦!

内容的提问来源于stack exchange,提问作者Bartłomiej Szałach

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:59:21