杰森(Json)的“验证"为......而玩 [英] Json "Validate" for Play

查看:125
本文介绍了杰森(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"
}

我的人物类别定义如下

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

推荐答案

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

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 的,以确保我们处理的是可以转换为.无需在这里重新发明轮子.

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

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.

注意,您也可以使用理解来写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天全站免登陆