Play/Scala JSON 内的 if 语句解析?

If statements within Play/Scala JSON parsing?

有没有办法在使用 Scala/Play 解析 json 时执行条件逻辑?

例如,我想做如下事情:

implicit val playlistItemInfo: Reads[PlaylistItemInfo] = (
    (if(( (JsPath \ "type1").readNullable[String]) != null){ (JsPath \ "type1" \ "id").read[String]} else {(JsPath \ "type2" \ "id").read[String]}) and
      (JsPath \ "name").readNullable[String]
    )(PlaylistItemInfo.apply _)

在我假设的 JSON 解析示例中,有两种可能的方法来解析 JSON。如果该项目是 "type1",那么 JSON 中将有一个 "type1" 的值。如果 JSON 中不存在或其值为 null/empty,那么我想改为阅读 JSON 节点 "type2"。

上面的示例不起作用,但它让您了解我正在尝试做什么。

这可能吗?

使用 JSON 组合器执行此操作的正确方法是使用 orElse。组合子的每一部分都必须是 Reads[YourType],所以 if/else 不太有效,因为你的 if 子句不是 return Boolean,它 returns Reads[PlaylistItemInfo] 对照 null 进行检查,后者始终为 trueorElse 让我们 结合 一个 Reads 寻找 type1 字段,第二个寻找 type2 字段作为后备。

这可能不符合您的确切结构,但我的想法是:

import play.api.libs.json._
import play.api.libs.functional.syntax._

case class PlaylistItemInfo(id: Option[String], tpe: String)

object PlaylistItemInfo {
    implicit val reads: Reads[PlaylistItemInfo] = (
        (__ \ "id").readNullable[String] and
        (__ \ "type1").read[String].orElse((__ \ "type2").read[String])
    )(PlaylistItemInfo.apply _)
}

// Read type 1 over type 2
val js = Json.parse("""{"id": "test", "type1": "111", "type2": "2222"}""")

scala> js.validate[PlaylistItemInfo]
res1: play.api.libs.json.JsResult[PlaylistItemInfo] = JsSuccess(PlaylistItemInfo(Some(test),111),)

// Read type 2 when type 1 is unavailable
val js = Json.parse("""{"id": "test", "type2": "22222"}""")

scala> js.validate[PlaylistItemInfo]
res2: play.api.libs.json.JsResult[PlaylistItemInfo] = JsSuccess(PlaylistItemInfo(Some(test),22222),)

// Error from neither
val js = Json.parse("""{"id": "test", "type100": "fake"}""")

scala> js.validate[PlaylistItemInfo]
res3: play.api.libs.json.JsResult[PlaylistItemInfo] = JsError(List((/type2,List(ValidationError(error.path.missing,WrappedArray())))))