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

Gson转换Scala Case Class为JSON时Map属性值丢失问题求助

解决Gson序列化Scala Case Class中Map为空的问题

问题原因

Gson是为Java生态设计的序列化库,默认仅支持Java标准集合类型(如java.util.HashMap),无法识别Scala自带的Map集合。因此直接用默认Gson实例序列化Scala Case Class中的Scala Map时,会输出空对象{}。

解决方案

方案1:将Scala Map转换为Java Map

借助Scala的CollectionConverters工具类,把Scala Map转为Java兼容的Map类型,再进行序列化:

import com.google.gson.Gson
import scala.jdk.CollectionConverters._

case class Example(SomeProperty: String, FruitMap: Map[String, String] = Map.empty[String, String])

val fruitMap = Map("fruit1" -> "apple", "fruit2" -> "banana", "fruit3" -> "orange")
val example1 = Example("prop1", fruitMap)

// 手动转换Scala Map为Java Map后构建可序列化的结构
val serializableData = Map(
  "SomeProperty" -> example1.SomeProperty,
  "FruitMap" -> example1.FruitMap.asJava
)

val json = new Gson().toJson(serializableData)
// 输出结果:{"SomeProperty":"prop1","FruitMap":{"fruit1":"apple","fruit2":"banana","fruit3":"orange"}}

方案2:自定义Gson TypeAdapter处理Scala Map

编写自定义的TypeAdapter,让Gson能够识别并正确序列化Scala Map,注册到GsonBuilder中使用:

import com.google.gson.{Gson, GsonBuilder, TypeAdapter, JsonWriter, JsonReader}
import scala.jdk.CollectionConverters._

// 针对Scala Map[String, String]的TypeAdapter
class ScalaStringMapAdapter extends TypeAdapter[Map[String, String]] {
  override def write(writer: JsonWriter, map: Map[String, String]): Unit = {
    writer.beginObject()
    map.foreach { case (key, value) =>
      writer.name(key).value(value)
    }
    writer.endObject()
  }

  override def read(reader: JsonReader): Map[String, String] = {
    // 如需反序列化可实现此方法,示例仅处理序列化
    val mutableMap = collection.mutable.Map.empty[String, String]
    reader.beginObject()
    while (reader.hasNext) {
      mutableMap.put(reader.nextName(), reader.nextString())
    }
    reader.endObject()
    mutableMap.toMap
  }
}

case class Example(SomeProperty: String, FruitMap: Map[String, String] = Map.empty[String, String])

val fruitMap = Map("fruit1" -> "apple", "fruit2" -> "banana", "fruit3" -> "orange")
val example1 = Example("prop1", fruitMap)

// 注册自定义适配器并创建Gson实例
val gson = new GsonBuilder()
  .registerTypeAdapter(classOf[Map[String, String]], new ScalaStringMapAdapter())
  .create()

val json = gson.toJson(example1)
// 输出包含Map内容的正确JSON

方案3:改用Scala原生JSON库(推荐)

Gson并非Scala生态的最优选择,改用专门为Scala设计的JSON库(如Circe、Play JSON),可以原生支持Case Class和Scala集合,无需额外适配:

以Circe为例,先添加SBT依赖:

libraryDependencies ++= Seq(
  "io.circe" %% "circe-core" % "0.14.6",
  "io.circe" %% "circe-generic" % "0.14.6",
  "io.circe" %% "circe-parser" % "0.14.6"
)

然后编写代码:

import io.circe.generic.auto._
import io.circe.syntax._

case class Example(SomeProperty: String, FruitMap: Map[String, String] = Map.empty[String, String])

val fruitMap = Map("fruit1" -> "apple", "fruit2" -> "banana", "fruit3" -> "orange")
val example1 = Example("prop1", fruitMap)

// 直接序列化Case Class
val json = example1.asJson.noSpaces
// 输出结果:{"SomeProperty":"prop1","FruitMap":{"fruit1":"apple","fruit2":"banana","fruit3":"orange"}}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 12:01:25