如何使用circe将含蛇形type字段的JSON解析为Pascal Case枚举?
使用Circe解析JSON到Scala枚举数组
1. 添加Circe依赖
在SBT构建文件中引入必要的Circe依赖(版本可根据实际场景调整):
libraryDependencies ++= Seq( "io.circe" %% "circe-core" % "0.14.6", "io.circe" %% "circe-generic" % "0.14.6", "io.circe" %% "circe-parser" % "0.14.6" )
2. 定义完整的Scala枚举类型
先补全Variant枚举的具体字段(示例字段可根据实际需求替换):
enum Variant: case FirstVariant(name: String, value: Int) case SecondVariant(description: String, active: Boolean)
3. 实现Circe编解码器
Circe默认无法自动识别基于type字段区分的枚举,需要自定义编解码逻辑,以type值为路由标识:
首先导入Circe核心包:
import io.circe._ import io.circe.generic.semiauto._ import io.circe.parser.decode import io.circe.syntax._
然后为每个枚举case生成基础编解码器,再实现顶层Variant的编解码:
// 为单个枚举case自动推导编解码器 implicit val firstVariantDecoder: Decoder[Variant.FirstVariant] = deriveDecoder implicit val firstVariantEncoder: Encoder[Variant.FirstVariant] = deriveEncoder implicit val secondVariantDecoder: Decoder[Variant.SecondVariant] = deriveDecoder implicit val secondVariantEncoder: Encoder[Variant.SecondVariant] = deriveEncoder // 顶层解码器:读取type字段,路由到对应case的解析逻辑 implicit val variantDecoder: Decoder[Variant] = Decoder.instance { c => c.get[String]("type").flatMap { case "first_variant" => c.as[Variant.FirstVariant] case "second_variant" => c.as[Variant.SecondVariant] case unknownType => Left(DecodingFailure(s"未知枚举类型: $unknownType", c.history)) } } // 顶层编码器:根据枚举case添加对应的type字段 implicit val variantEncoder: Encoder[Variant] = Encoder.instance { case f: Variant.FirstVariant => f.asJson.mapObject(_.add("type", Json.fromString("first_variant"))) case s: Variant.SecondVariant => s.asJson.mapObject(_.add("type", Json.fromString("second_variant"))) }
4. 测试解析与序列化
验证JSON数组和枚举数组的相互转换:
// 测试用JSON字符串 val jsonStr = """ [ {"type": "first_variant", "name": "Demo1", "value": 42}, {"type": "second_variant", "description": "Demo2", "active": true} ] """ // 解析JSON到List[Variant] val parseResult: Either[Error, List[Variant]] = decode[List[Variant]](jsonStr) parseResult match { case Right(variants) => variants.foreach(println) case Left(err) => println(s"解析失败: ${err.getMessage}") } // 序列化枚举数组回JSON val testVariants = List( Variant.FirstVariant("Foo", 100), Variant.SecondVariant("Bar", false) ) val serializedJson = testVariants.asJson println(serializedJson.spaces2)
关键说明
- 核心逻辑依赖
type字段作为枚举case的区分标识,解析时先读取该字段值,再路由到对应case的解码器;序列化时自动为每个case的JSON对象追加type字段。 - 若枚举case包含复杂字段,Circe的
semiauto推导器可自动处理字段的编解码,无需手动编写每个字段的逻辑。
内容的提问来源于stack exchange,提问作者Max Smirnov
相关产品推荐
相关产品推荐

