0

我正在写一个JSON Writes. 在models/Users.scala,我定义了一个implicit带有定义的对象implicit

object UserImplicits {

  /*Writes (write to JsValue) are used by toJson method of Json object to convert data (say the model) to JsValue*/
    implicit val profileWrites:Writes[UserProfile] = (
        (JsPath \ "confirmed").write[Boolean] and
          (JsPath \ "email").write[String] and
          (JsPath \ "firstname").write[String] and
          (JsPath \ "lastname").write[String]
        ) (unlift(UserProfile.unapply))

      implicit val userWrites: Writes[User] = (
        (JsPath \ "id").write[UUID] and
          (JsPath \ "user-profile").write[UserProfile]
        ) (unlift(User.unapply))

      implicit val usersResourceWrites:Writes[UsersResource] = (
        (JsPath \ "id").write[String] and
          (JsPath \ "url").write[String] and
          (JsPath \ "user").write[User]
        ) (unlift(UsersResource.unapply))


  /*Reads (read from JsValue) is used by Json object's as or asOpt methods to convert JsValue to some other data, eg your model*/

      implicit val profileReads:Reads[UserProfile] = (
        (JsPath \ "confirmed").read[Boolean] and
          (JsPath \ "email").read[String] and
          (JsPath \ "firstname").read[String] and
          (JsPath \ "lastname").read[String]
        ) (UserProfile.apply _)

      implicit val userReads: Reads[User] = (
        (JsPath \ "id").read[UUID] and
          (JsPath \ "user-profile").read[UserProfile]
        ) (User.apply _)

      implicit val usersResourceReads: Reads[UsersResource] = (
        (JsPath \ "id").read[String] and
          (JsPath \ "url").read[String] and
          (JsPath \ "user").read[User]
        ) (UsersResource.apply _)

}

在我的controller课堂上,我已经导入models._并定义了控制器,如下所示:

import models._

import scala.concurrent.{ExecutionContext, Future}

class UserController @Inject()(cc: ControllerComponents)(implicit exec: ExecutionContext) extends AbstractController(cc){

  //TODOM - remove hard coded response
  def addUser = Action.async{ implicit request => {
    println("addUser controller called")
    val user = User(UUID.randomUUID(),UserProfile(true,"m@m.com","m","c"))
    val userResource = UsersResource(user.id.toString(),"/ws/users",user)
    val json = Json.toJson(userResource); //converts the model to JsValue using Writes defined in Users model class
    println("returning json:",Json.prettyPrint(json))
    Future{Ok(json)}}
  }

我收到以下编译错误。

No Json serializer found for type models.UsersResource. Try to implement an implicit Writes or Format for this type.对于代码val json = Json.toJson(userResource);

问题似乎是 Play 找不到隐式写入。如果我在控制器中移动隐式定义而不是在模型中定义,则代码有效。如何使 model/user.scala 中定义的隐式在控制器类中可见?

4

2 回答 2

0

如果您将您的隐式移动到您正在(反)序列化的类的伴随对象中,编译器将自动拾取它们。所以,如果这是你的UserProfile案例类:

case class UserProfile(confirmed: Boolean,
                       email: String,
                       firstname: String,
                       lastname: String)

...然后你可以在下面写这个(关键是它的名称相同):

object UserProfile {
  implicit val profileWrites: Writes[UserProfile] = //...
  implicit val profileReads: Reads[UserProfile] = //...
}

或者,只使用一个Format(将 aReads和 aWrites合二为一),如果 JSON 结构与您的案例类字段名称完全对应,则可以轻松实现:

object UserProfile {
  implicit val profileFormat: Format[UserProfile] = Json.format[UserProfile]

或者,您可以import UserImplicits._.

于 2018-02-21T09:23:16.437 回答
0

我必须创建另一个对象(不是伴随对象)并在那里添加隐式定义。

要使用这些隐式,请在需要隐式的文件中使用 import models.UserImplicits._。

object UserImplicits {

    /*Writes (write to JsValue) are used by toJson method of Json object to convert data (say the model) to JsValue*/
    implicit val profileWrites:Writes[UserProfile] = (
      (JsPath \ "confirmed").write[Boolean] and
        (JsPath \ "email").writeNullable[String] and
        (JsPath \ "firstname").writeNullable[String] and
        (JsPath \ "lastname").writeNullable[String]
      ) (unlift(UserProfile.unapply))


    implicit val userWrites: Writes[User] = (
      (JsPath \ "id").write[UUID] and
        (JsPath \ "user-profile").write[UserProfile]
      ) (unlift(User.unapply))

   implicit val usersResourceWrites:Writes[UsersResource] = (
      (JsPath \ "id").write[String] and
        (JsPath \ "url").write[String] and
        (JsPath \ "user").write[User]
      ) (unlift(UsersResource.unapply))


    /*Reads (read from JsValue) is used by Json object's as or asOpt methods to convert JsValue to some other data, eg your model*/

  implicit val profileReads:Reads[UserProfile] = (
    (JsPath \ "confirmed").read[Boolean] and
      (JsPath \ "email").readNullable[String] and
      (JsPath \ "firstname").readNullable[String] and
      (JsPath \ "lastname").readNullable[String]
    ) (UserProfile.apply _)


    implicit val userReads: Reads[User] = (
      (JsPath \ "id").read[UUID] and
        (JsPath \ "user-profile").read[UserProfile]
      ) (User.apply _)

    implicit val usersResourceReads: Reads[UsersResource] = (
      (JsPath \ "id").read[String] and
        (JsPath \ "url").read[String] and
        (JsPath \ "user").read[User]
      ) (UsersResource.apply _)

}
于 2018-03-19T05:49:29.047 回答