播放:如何验证JsValue

时间:2014-01-18 19:28:23

标签: json scala playframework

这是一个非常简单的JSON片段......

[
  {
    "email": "fred@flintstones.com",
    "name": "fred",
    "trash": "ignore"
  }
]

...需要在处理之前进行验证:

val validateUser: Reads[JsValue] = (
  (__ \ 'email).read(email) ~
  (__ \ 'name).read[String]
).tupled ~> implicitly[Reads[JsValue]]

验证程序有效......但生成的JsValue仍然包含trash字段,应该过滤掉该字段:

scala> val user = Json.obj(
     | "email" -> "fred@flintstones.com",
     | "name" -> "fred", "trash" -> "ignore")
user: play.api.libs.json.JsObject = {"email":"fred@flintstones.com","name":"fred","trash":"ignore"}

scala> val userValidator: Reads[JsValue] = (
     | (__ \ 'email).read(email) ~
     | (__ \ 'name).read[String]).tupled ~> implicitly[Reads[JsValue]]
userValidator: play.api.libs.json.Reads[play.api.libs.json.JsValue] = play.api.libs.json.Reads$$anon$3$$anon$4@77d7654e

scala> userValidator.reads(user)
res0: play.api.libs.json.JsResult[play.api.libs.json.JsValue] = JsSuccess({"email":"fred@flintstones.com","name":"fred","trash":"ignore"},)

然后,我试图像这样修改验证器......

val validateUser: Reads[(String, String)] = (
  (__ \ 'email).read(email) ~
  (__ \ 'name).read[String]
).tupled

...这次生成的元组不再按预期包含trash字段:

scala> val userValidator: Reads[(String,String)] = (
     | (__ \ 'email).read(email) ~
     | (__ \ 'name).read[String]).tupled
userValidator: play.api.libs.json.Reads[(String, String)] = play.api.libs.json.Reads$$anon$8@24ccd12b

scala> userValidator.reads(user)
res1: play.api.libs.json.JsResult[(String, String)] = JsSuccess((fred@flintstones.com,fred),)

现在问题是:如何在没有JsValue字段的情况下让验证器返回trash?为什么~> implicitly[Reads[JsValue]]会保留它?

3 个答案:

答案 0 :(得分:0)

根据我的理解,验证器的功能不是转换JSON,而是验证它是否具有某些字段,并且它们是预期的类型。

如果您想转换JSON以删除“垃圾”,您可以:

userValidator.reads(user).map(js => js - "trash")

或仅包含某些字段:

userValidator.reads(user).map(js => Json.obj("name" -> js \ "name", "email" -> js \ "email"))

你可能已经看过this文章了,但是它非常有用我还是把它包括在内。

答案 1 :(得分:0)

您的解析器验证每个输入并在成功时接受原始输入。

您的问题是关于JSON转换(在official documentation中描述)

您必须保留有效输入,如下所示:

val validateUser = (
  (( __ \ 'email ).read(email) ~> ( __ \ 'email ).json.pickBranch) ~
  ((__ \ 'name).read[String] ~> ( __ \ 'name ).json.pickBranch)
) reduce

答案 2 :(得分:0)

Dan和Isammoc的解决方案都有效......但是看看Json文档,我认为正确的方法应该如下:

val emptyObj = __.json.put(Json.obj())

...

val validateUser = (
  (( __ \ 'email).json.pickBranch(Reads.of[JsString] keepAnd Reads.email)) ~
  (( __ \ 'name).json.pickBranch) ~
  (( __ \ 'optional).json.pickBranch or emptyObj)
).reduce

正如您所看到的,我还添加了电子邮件验证并定义了emtpyObj来模拟JsPath.readNullable。我希望有所帮助。