I'm scala newbie and trying to understand it's base concepts. With use of play/scala/slick I'm trying to implement trivial app which allows user to perform CRUD operations on another users. So problem I faces is that I don't understand how I should use implicit conversions to convert model object to DTO object.
Here is what I've got so far:

Application.scala (Controller class):

//returns list of users def users = Action.async { val userList = userDAO.all() userList .map { list => Ok(list.map(elem => Json.toJson(elem))) } .recover { case _ => InternalServerError } } 

User.scala (model object, represents entry in database):

case class User(id: Long, login: String, password: String) extends BaseEntity 

UserDto.scala (DTO, object, representing User in user list):

case class UserDto(id: Long, login: String) { implicit def userWriter = Json.writes[UserDto] implicit def user2UserDto(user: User): UserDto = UserDto(user.id, user.login) } 

In code above, at #1 tag, I get a error which states that User can't be converted to json. Exact error message: Error:(40, 53) No Json serializer found for type Application.this.userDAO.Entity. Try to implement an implicit Writes or Format for this type. .map { list => Ok(list.map(elem => Json.toJson(elem))) }. How and where should I implement conversion from User to UserDto so that it works and not, say, ugly?

For example, in Java I would implement each Dto object with public User to() and public static UserDto from(User user) so that I can convert them. Should I do the same in scala or there is more elegant way to accomplish this task?

EDITION Edited version of users method:

def users = Action.async { val userList = userDAO.all() userList .map { list => Ok(list.map(elem => Json.toJson(elem : UserDto))) } .recover { case _ => InternalServerError } } 

Have the following compiler errors:

Error:(41, 24) not enough arguments for method apply: (implicit writeable: play.api.http.Writeable[Seq[play.api.libs.json.JsValue]])play.api.mvc.Result in class Status. Unspecified value parameter writeable. .map { list => Ok(list.map(elem => Json.toJson(elem : UserDto))) } Error:(41, 24) Cannot write an instance of Seq[play.api.libs.json.JsValue] to HTTP response. Try to define a Writeable[Seq[play.api.libs.json.JsValue]] .map { list => Ok(list.map(elem => Json.toJson(elem : UserDto))) } 

It seems that compiler doesn't see userWriter in UserDto object.

2

1 Answer

Don't define the implicits inside the case class. Define them in a companion object:

case class UserDto(id: Long, login: String) object UserDto { implicit def userWriter = Json.writes[UserDto] implicit def user2UserDto(user: User): UserDto = UserDto(user.id, user.login) } 

When you define them inside a case class, they become instance methods only available from an instance of the class. When you define them on a companion object, they are defined globally (not tied to an instance) and they are equivalent to static methods in java. From there, scala's implicit resolution mechanism can find them.

3

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy