播放未找到隐式定义
Play not finding implicit definition
我在写一个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
class 中,我导入了 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 找不到隐式 Writes。如果我在控制器中移动隐式定义而不是在模型中定义,则代码有效。我怎样才能使 model/user.scala 中定义的隐式在控制器中可见 class?
如果您将隐式对象移动到您正在(反)序列化的 classes 的伴随对象中,编译器将自动拾取它们。所以,如果这是你的 UserProfile
案例 class:
case class UserProfile(confirmed: Boolean,
email: String,
firstname: String,
lastname: String)
...那你就写在下面(重点是同名):
object UserProfile {
implicit val profileWrites: Writes[UserProfile] = //...
implicit val profileReads: Reads[UserProfile] = //...
}
或者,只使用一个 Format
(这是一个 Reads
和一个 Writes
合二为一),如果 JSON 结构对应,可以很容易地实现完全符合您的情况 class 字段名称:
object UserProfile {
implicit val profileFormat: Format[UserProfile] = Json.format[UserProfile]
或者,您可以 import UserImplicits._
。
我必须创建另一个对象(不是伴随对象)并在其中添加隐式定义。
要使用这些隐式,请在需要隐式的文件中使用 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 _)
}
我在写一个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
class 中,我导入了 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 找不到隐式 Writes。如果我在控制器中移动隐式定义而不是在模型中定义,则代码有效。我怎样才能使 model/user.scala 中定义的隐式在控制器中可见 class?
如果您将隐式对象移动到您正在(反)序列化的 classes 的伴随对象中,编译器将自动拾取它们。所以,如果这是你的 UserProfile
案例 class:
case class UserProfile(confirmed: Boolean,
email: String,
firstname: String,
lastname: String)
...那你就写在下面(重点是同名):
object UserProfile {
implicit val profileWrites: Writes[UserProfile] = //...
implicit val profileReads: Reads[UserProfile] = //...
}
或者,只使用一个 Format
(这是一个 Reads
和一个 Writes
合二为一),如果 JSON 结构对应,可以很容易地实现完全符合您的情况 class 字段名称:
object UserProfile {
implicit val profileFormat: Format[UserProfile] = Json.format[UserProfile]
或者,您可以 import UserImplicits._
。
我必须创建另一个对象(不是伴随对象)并在其中添加隐式定义。
要使用这些隐式,请在需要隐式的文件中使用 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 _)
}