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
相关产品推荐
相关产品推荐

