查看源代码,我们可以看到原因。任何匹配 a 的值JsNumber
都toInt
调用了它:
implicit object IntReads extends Reads[Int] {
def reads(json: JsValue) = json match {
case JsNumber(n) => JsSuccess(n.toInt)
case _ => JsError(Seq(JsPath() -> Seq(ValidationError("error.expected.jsnumber"))))
}
}
为了避免这种情况,我们可以实现一个Reads[Int]
不会验证非整数的新方法:
import play.api.libs.json._
import play.api.libs.json.Reads._
import play.api.libs.functional.syntax._
import play.api.data.validation._
implicit object WholeIntReads extends Reads[Int] {
def reads(json: JsValue) = json match {
case JsNumber(n) if(n.isValidInt) => JsSuccess(n.toInt)
case _ => JsError(Seq(JsPath() -> Seq(ValidationError("error.expected.jsnumber"))))
}
}
并像这样使用它:
case class Person(val name: String, val age: Int, val role: String)
object Person {
implicit val residentReads: Reads[Person] = (
(JsPath \ "name").read[String](minLength[String](3)) and
(JsPath \ "age").read[Int](WholeIntReads keepAnd min(0)) and
(JsPath \ "role").read[String]
)(Person.apply _)
}
(您的示例代码中有一些不一致之处,所以我修复了它们以进行编译。唯一相关的行是age
。)
结果:
scala> Json.parse("""{"name": "Jack","age": 22.4,"role": "Coder"}""").validate[Person]
res13: play.api.libs.json.JsResult[Person] = JsError(List((/age,List(ValidationError(error.expected.jsnumber,WrappedArray())))))
scala> Json.parse("""{"name": "Jack","age": 22,"role": "Coder"}""").validate[Person]
res14: play.api.libs.json.JsResult[Person] = JsSuccess(Person(Jack,22,Coder),)
scala> Json.parse("""{"name": "Jack","age": -22,"role": "Coder"}""").validate[Person]
res15: play.api.libs.json.JsResult[Person] = JsError(List((/age,List(ValidationError(error.min,WrappedArray(0))))))
请注意,我正在使用validate[T]
而不是抛出异常,因为这是最佳实践。这将允许ValidationError
s 在不需要任何异常的情况下累积和处理。