gpt4 book ai didi

json - 如何避免 Play Framework Json Reads 提供的自动转换,而是获取异常

转载 作者:行者123 更新时间:2023-12-01 08:12:37 26 4
gpt4 key购买 nike

如果可以进行转换,Reads 似乎会为我自动转换。例如, float -> 整数。比如代码获取json如下,

{
"name": "Jack",
"age": 22.4,
"role": "Coder"
}

类 Person 的实例将具有 age 字段 22,而不是得到无效参数异常。如果在这种情况下我确实想要一个异常(exception),那么最好的解决方案是什么?非常感谢。

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

object Person {
implicit val residentReads: Reads[Resident] = (
(JsPath \ "name").read[String](minLength[String](3)) and
(JsPath \ "age").read[Int](min(0)) and
(JsPath \ "role").readNullable[String]
)(Resident.apply _)

...
}

最佳答案

查看源代码,我们就知道为什么了。任何匹配 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 累积并在不需要任何异常的情况下进行处理。

关于json - 如何避免 Play Framework Json Reads 提供的自动转换,而是获取异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26856526/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com