Json“验证"为......而玩 [英] Json "Validate" for Play

查看:23
本文介绍了Json“验证"为......而玩的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于 request.body 上的 validate 方法,它将 json 对象的属性名称和值类型与模型定义中定义的属性名称和值类型相匹配.现在,如果我要向 json 对象添加一个额外的属性并尝试对其进行验证,它会在不应该传递的情况下作为 JsSuccess 传递.

For the validate method on request.body it matches the attribute name and value type of the json object to those defined in the model definition. Now if I were to add an extra attribute to the json object and try to validate it, it passes as a JsSuccess when it shouldn't.

{ 
    "Name": "Bob",
    "Age": 20,
    "Random_Field_Not_Defined_in_Models": "Test"
}

我的Person类定义如下

My Person Class is defined as follows

case class Person(name: String, age: Int)

推荐答案

我假设您一直在使用内置的 Reads[T]Format[T]Json.reads[T] 为您提供的/code> 转换器,例如:

I'm assuming you've been using the built-in Reads[T] or Format[T] converters that Play gives you via Json.reads[T], e.g.:

import play.api.libs.json._

val standardReads = Json.reads[Person]

虽然这些超级很方便,但如果您需要附加验证,您必须定义一个自定义的Reads[Person]类;但幸运的是,我们仍然可以利用内置的 JSON-to-case-class 宏来进行基本的检查和转换,如果一切正常,然后添加额外的自定义检查层:

While these are super-handy, if you need additional validation, you'll have to define a custom Reads[Person] class; but fortunately we can still leverage the built-in JSON-to-case-class macro to do the basic checking and conversion, and then add an extra layer of custom checks if things seem OK:

val standardReads = Json.reads[Person]

val strictReads = new Reads[Person] {
  val expectedKeys = Set("name", "age")

  def reads(jsv:JsValue):JsResult[Person] = {
    standardReads.reads(jsv).flatMap { person =>
      checkUnwantedKeys(jsv, person)
    }
  }

  private def checkUnwantedKeys(jsv:JsValue, p:Person):JsResult[Person] = {
    val obj = jsv.asInstanceOf[JsObject]
    val keys = obj.keys
    val unwanted = keys.diff(expectedKeys)
    if (unwanted.isEmpty) {
      JsSuccess(p)
    } else {
      JsError(s"Keys: ${unwanted.mkString(",")} found in the incoming JSON")
    }
  } 
} 

注意我们如何利用standardReads 首先,以确保我们正在处理可以转换为 Person.无需在这里重新发明轮子.

Note how we utilize standardReads first, to make sure we're dealing with something that can be converted to a Person. No need to reinvent the wheel here.

如果我们从 standardReads 得到 JsError,我们使用 flatMap 来有效地短路转换 - 即我们只调用 checkUnwantedKeys 如果需要.

We use flatMap to effectively short-circuit the conversion if we get a JsError from standardReads - i.e. we only call checkUnwantedKeys if needed.

checkUnwantedKeys 仅使用 JsObject实际上只是一个 Map 的包装器,所以我们可以很容易地检查键的名称反对白名单.

checkUnwantedKeys just uses the fact that a JsObject is really just a wrapper around a Map, so we can easily check the names of the keys against a whitelist.

注意,您也可以使用 for-comprehension 编写 flatMap,如果您需要更多检查阶段,它看起来会更清晰:

Note that you could also write that flatMap using a for-comprehension, which starts to look a lot cleaner if you need even more checking stages:

for {
    p <- standardReads.reads(jsv)
    r1 <- checkUnexpectedFields(jsv, p)
    r2 <- checkSomeOtherStuff(jsv, r1)
    r3 <- checkEvenMoreStuff(jsv, r2)
} yield r3

这篇关于Json“验证"为......而玩的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆