【问题标题】:Defining cross-attribute Json Validators for a case class in Play Framework 2.3.x (Scala)在 Play Framework 2.3.x (Scala) 中为案例类定义跨属性 Json 验证器
【发布时间】:2015-07-17 08:47:47
【问题描述】:

我知道可以定义我们想要匹配某些给定 json 的 Case 类(我们使用 JsValue.validate[T]):

例如:

case class UpdateDashboardModel(id: Long,
                            maybeName: Option[String],
                            containers: Option[List[UpdateContainerModel]],
                            description: Option[String])

然后我们必须编写一个Reads[T] 来定义如何将json 对象实际转换为我们的案例类的实例(并且可以选择为各个属性定义一些自定义验证器):

  val exists: Reads[Long] =
    Reads.LongReads.filter(ValidationError("Dashboard does not exist"))(long => Dashboard.findById(long).isDefined)


  implicit val reads: Reads[UpdateDashboardModel] = (
    (JsPath \ "id").read[Long](exists) and
    (JsPath \ "name").readNullable[String] and
    (JsPath \ "containers").readNullable[List[UpdateContainerModel]] and
    (JsPath \ "description").readNullable[String]) (UpdateDashboardModel.apply _ )

在这个例子中,我对给定的 id 运行一个简单的验证 -> 它必须存在于数据库中,否则我必须抛出一个错误。

问题是,我似乎无法为需要 两个 属性的东西编写验证器。

例如,我想编写一个简短的验证器,它接受 id name 属性,因为我想检查是否名称尚未被另一个仪表板使用(如果它是当前仪表板,没关系)。

有人能想出办法吗?

提前致谢。

【问题讨论】:

  • 通常这不是你应该放入 JSON 验证器的东西。
  • @Ryan 我想将与验证相关的所有内容保存在一个地方,以便在我的控制器中,代码非常简单,即验证是否成功,然后执行此操作,否则返回 400带有错误消息的 http 响应。

标签: json scala validation playframework-2.0 playframework-2.3


【解决方案1】:

好吧,它不漂亮,但我认为这样的事情应该可以工作......让我们假设isNameAvailable 是一个确保名称尚未被另一个仪表板使用的函数,如果名称可用则返回true(否则为假)。

import play.api.data.validation.ValidationError

implicit val reads: Reads[UpdateDashboardModel] = (
  (JsPath \ "id").read[Long](exists) and
  (
    (JsPath \ "id").read[Long] and
    (JsPath \ "name").readNullable[String]
  ).tupled.filter(
    ValidationError("Name is already in use")
  )
  { case (id, name) => isNameAvailable(name, id) }.map(t => t._2) and
  (JsPath \ "containers").readNullable[List[UpdateContainerModel]] and
  (JsPath \ "description").readNullable[String]) (UpdateDashboardModel.apply _ )

我个人觉得tupled.filter 语法有点奇怪,但这就是我能够克服您遇到的问题的方法。

【讨论】:

  • 我明天会测试这段代码,如果可行,我会检查你的答案。
  • 谢谢。我可能会就此写一篇博文来提醒自己如何做到这一点,但我会引用你作为这方面的来源。
  • 是的,这也不是我自己“发明”的——如果我没记错的话,我最初是从 Play Framework 的 Google 小组中找到这个解决方案的。
猜你喜欢
  • 2015-03-05
  • 2014-12-06
  • 2015-02-11
  • 1970-01-01
  • 1970-01-01
  • 2014-06-27
  • 1970-01-01
  • 2014-07-31
相关资源
最近更新 更多