Scala将无固定Schema JSON转为ListMap并保留全量键插入顺序的问题
Scala固定两层JSON转有序ListMap解决方案
前置说明
当前场景明确JSON仅两层嵌套,且需要保留所有层级键的原始顺序,以下两种方案均可满足需求:
方案1:配置Jackson默认Map实现(低代码,无需手动类型判断)
通过配置Jackson的Scala模块,指定所有JSON对象反序列化时默认使用ListMap实现,无需手动处理类型推断,内外层键顺序均可完全保留。
代码示例
// 导入依赖 import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.module.scala.DefaultScalaModule import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper import com.fasterxml.jackson.databind.ObjectMapper import scala.collection.immutable.ListMap // 初始化并配置Mapper val mapper = new ObjectMapper() with ScalaObjectMapper // 注册Scala模块,指定Map默认用ListMap实现 mapper.registerModule(DefaultScalaModule.copy(mapFactory = ListMap.mapFactory)) // 禁用Map键自动排序,完全对齐原始JSON顺序 mapper.disable(DeserializationFeature.ORDER_MAP_ENTRIES_BY_KEYS) // 原始JSON字符串 val originalJSONString = """ { "outerKey1": "", "outerKey2": "", "outerKey3": { "innerKey1": "", "innerKey2": "", "innerKey3": "" } } """ // 直接反序列化,值类型自动适配:字符串为String,嵌套对象为ListMap val jsonListMap = mapper.readValue[ListMap[String, Any]](originalJSONString) // 序列化输出,键顺序和原始JSON完全一致 println(mapper.writeValueAsString(jsonListMap))
方案2:Either强类型适配(更安全,避免运行时类型转换异常)
因为JSON结构固定为两层,外层值仅可能是字符串或字符串映射,使用Either类型可以在编译期约束结构,无需运行时强转,使用更安全。
代码示例
import com.fasterxml.jackson.core.`type`.TypeReference // 定义两层结构的TypeReference val twoLevelMapType = new TypeReference[ListMap[String, Either[String, ListMap[String, String]]]] {} // 反序列化 val jsonListMap = mapper.readValue(originalJSONString, twoLevelMapType) // 使用时通过模式匹配判断值类型,无类型转换风险 jsonListMap.foreach { case (outerKey, value) => value match { case Left(strValue) => println(s"键$outerKey为字符串类型,值:$strValue") case Right(innerMap) => println(s"键$outerKey为嵌套映射,内层键顺序:${innerMap.keys.mkString(",")}") } }
扩展说明
如果后续需要支持任意层级的嵌套JSON,可以通过定义代数数据类型(ADT)配合自定义反序列化器实现,示例结构如下:
sealed trait OrderedJsonValue case class StrValue(value: String) extends OrderedJsonValue case class MapValue(value: ListMap[String, OrderedJsonValue]) extends OrderedJsonValue
这种基于类型特征匹配的方案可复用至所有半结构化数据处理场景,无需预定义全量Schema即可保留结构信息与顺序。
内容的提问来源于stack exchange,提问作者NMcD
相关产品推荐
相关产品推荐

