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

Scala Play JSON解析同字段多schema时自定义Either类型Format语法问题求解

问题原因&修正方案

你代码的核心错误有3处:

  1. reads逻辑中,validate[SettingLeft]得到的结果是JsResult[SettingLeft],你调用.map(SettingLeft.apply)等于什么都没做,也没有转成Setting类型,导致orElse两边类型不匹配,报语法错误
  2. writes逻辑中,Setting类没有either成员,你直接访问.parameter才是目标Either类型;同时你直接序列化parameter的值,丢失了active、type两个外层字段
  3. 你给Setting定义的两个隐式apply重载容易引发隐式冲突,不需要保留

修正后的完整代码

import play.api.libs.json._

case class Xparameter(x1: Int, x2: String)
object Xparameter {
  implicit val format: Format[Xparameter] = Json.format[Xparameter]
}

case class Color(blue: Boolean, green: Boolean)
object Color {
  implicit val format: Format[Color] = Json.format[Color]
}

case class Yparameter(y1: Int, y2: String, y3: Color)
object Yparameter {
  implicit val format: Format[Yparameter] = Json.format[Yparameter]
}

case class SettingLeft(
                        active: Boolean,
                        `type`: String,
                        parameter: Xparameter
                      )
object SettingLeft {
  implicit val format: Format[SettingLeft] = Json.format[SettingLeft]
}

case class SettingRight(
                         active: Boolean,
                         `type`: String,
                         parameter: List[Yparameter]
                       )
object SettingRight {
  implicit val format: Format[SettingRight] = Json.format[SettingRight]
}

case class Setting(
                    active: Boolean,
                    `type`: String,
                    parameter: Either[Xparameter, List[Yparameter]]
                  )
object Setting {
  implicit val format: Format[Setting] = new Format[Setting] {
    override def reads(json: JsValue): JsResult[Setting] = {
      // 先尝试解析为SettingLeft,转成Setting,失败再尝试解析为SettingRight
      json.validate[SettingLeft].map(left => 
        Setting(left.active, left.`type`, Left(left.parameter))
      ).orElse(
        json.validate[SettingRight].map(right => 
          Setting(right.active, right.`type`, Right(right.parameter))
        )
      )
    }

    override def writes(o: Setting): JsValue = o.parameter match {
      case Left(xParam) => 
        // 转成SettingLeft再序列化,保证结构和原JSON一致
        Json.toJson(SettingLeft(o.active, o.`type`, xParam))
      case Right(yParams) => 
        // 转成SettingRight再序列化
        Json.toJson(SettingRight(o.active, o.`type`, yParams))
    }
  }

  // 外层容器的format,对应你示例的根JSON结构
  case class RootSettings(settings: List[Setting])
  object RootSettings {
    implicit val format: OFormat[RootSettings] = Json.format[RootSettings]
  }
}

测试验证示例

// 测试解析你提供的JSON示例
val jsonStr = """{
   "settings":[
      {
         "active":false,
         "parameter":{
            "x1":0,
            "x2":"Simple"
         },
         "type":"sometype"
      },
      {
         "active":true,
         "parameter":[
            {
               "y1":100,
               "y2":"east",
               "y3":{
                  "blue":true,
                  "green":false
               }
            }
         ],
         "type":"someDifferentType"
      }
   ]
}"""

val parseResult = Json.parse(jsonStr).validate[Setting.RootSettings]
println(parseResult.isSuccess) // 输出true即为解析成功

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 00:09:02