我使用Play 2.3.4,并且我已经将一个简单的模型类定义为:
case class User(
@Id
id: Int,
name: String
) extends Model
object User {
def find() = { /* some code here */}
implicit object UserFormat extends Format[User] {
def reads(json: JsValue) = User(
(json \ "id").as[Int],
(json \ "name").as[String]
)
def writes(user: User) = JsObject(Seq("id" -> id, "name" -> name))
}
}
这很简单。但是我收到了编译错误:
Error:(31, -1) Play 2 Compiler:
/Users/asheshambasta/code/finit/app/models/users/User.scala:31: type mismatch;
found : models.devices.User
required: play.api.libs.json.JsResult[models.users.User]
我做错了什么?
答案 0 :(得分:2)
上面的代码有几个问题。您收到的编译错误是因为reads(json: JsValue)
应该返回JsResult
而不是模型。这是因为您在定义Reads
时需要考虑失败。 id
和name
也需要在user.id
中user.name
和writes
。这将编译:
object User {
implicit object UserFormat extends Format[User] {
def reads(json: JsValue) = JsSuccess(User(
(json \ "id").as[Int],
(json \ "name").as[String]
))
def writes(user: User) = Json.obj("id" -> user.id, "name" -> user.name)
}
}
但是,如果JSON中存在错误,则会抛出异常,因为as[T]
不安全。
scala> val testJs = Json.parse("""{"id":"2", "name": "test"}""")
testJs: play.api.libs.json.JsValue = {"id":"2","name":"test"}
scala> testJs.validate[User]
play.api.libs.json.JsResultException: JsResultException(errors:List((,List(ValidationError(error.expected.jsnumber,WrappedArray())))))
以简单对象的方式定义Reads
几乎总是不值得的,并且使用JSON组合器可以更好地完成。
object User {
implicit val reads: Reads[User] = (
(__ \ "id").read[Int] and
(__ \ "name").read[String]
)
implicit val writes: Writes[User] = (
(__ \ "id").write[Int] and
(__ \ "name").write[String]
)
}
JSON组合器不会像第一段代码那样抛出异常,并且在验证时会将所有错误累积到JsResult
中。在这样的简单情况下,JSON开始会更好:
object User {
implicit val format: Format[User] = Json.format[User]
}
还有Json.reads[T]
和Json.writes[T]
个宏,以防您需要自定义Reads
而不是Writes
或其他方式。