Scala Play JSON解析同字段多schema时自定义Either类型Format语法问题求解
问题原因&修正方案
你代码的核心错误有3处:
- reads逻辑中,
validate[SettingLeft]得到的结果是JsResult[SettingLeft],你调用.map(SettingLeft.apply)等于什么都没做,也没有转成Setting类型,导致orElse两边类型不匹配,报语法错误 - writes逻辑中,
Setting类没有either成员,你直接访问.parameter才是目标Either类型;同时你直接序列化parameter的值,丢失了active、type两个外层字段 - 你给
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
相关产品推荐
相关产品推荐

