0

Я новичок scala и пытаюсь понять его базовые понятия. С помощью play/scala/slick я пытаюсь реализовать тривиальное приложение, которое позволяет пользователю выполнять операции CRUD для других пользователей. Поэтому проблема, с которой я сталкиваюсь, заключается в том, что я не понимаю, как использовать неявные преобразования для преобразования объекта модели в объект DTO.
Вот что у меня до сих пор:Scala convert model object to DTO

Application.scala (класс Controller):

//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 (объектная модель, представляет собой запись в базе данных):

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

UserDto.scala (DTO , объект, представляющий пользователя в списке пользователей):

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

    implicit def user2UserDto(user: User): UserDto = UserDto(user.id, user.login) 
} 

В коде выше, в теге # 1, я получаю сообщение об ошибке, которое указывает, что User не может быть преобразован в json. Точное сообщение об ошибке: Ошибка: (40, 53) Нет сериализатора Json для типа Application.this.userDAO.Entity. Попробуйте реализовать неявные Writes или Format для этого типа. .map {list => Ok (list.map (elem => Json.toJson (elem)))}. Как и где следует преобразовывать пользователя из User в UserDto, чтобы он работал, а не, скажем, уродливым?

Например, в Java я бы реализовал каждый объект Dto с public User to() и public static UserDto from(User user), чтобы я мог их преобразовать. Должен ли я делать то же самое в scala или есть более элегантный способ выполнить эту задачу?

EDITION Отредактированный вариант users метода:

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

следующие ошибки компилятора:

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))) } 

Кажется, что компилятор не видит userWriter в UserDto объекта.

+0

'USERLIST .map {списка => Ok (userList.map (список => list.map (эль => Json.toJson (эль))))}' Почему вы карта над 'userList' но не используйте какие-либо элементы в нем, а вместо этого переместите его снова для каждого элемента? Также 'list.map (elem => Json.toJson (elem))' можно записать как 'list.map (Json.toJson)'. Пожалуйста, укажите точное сообщение об ошибке, которое вы получаете, при вызове 'toJson'. – sirius

+0

@sirius, я добавил сообщение об ошибке, которое я получаю при компиляции. Пожалуйста, см. Обновленный ответ. –

ответ

1

Не определяйте импликации внутри класс корпуса. Определить их в 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) 
} 

При определении их внутри корпуса класса, они становятся методы экземпляра доступны только из экземпляра класса. Когда вы определяете их на сопутствующем объекте, они определяются глобально (не привязаны к экземпляру), и они эквивалентны статическим методам в java. Оттуда механизм неявного разрешения Scala can find them.

+0

Спасибо, Альваро! Я исправил эту ошибку, но, к сожалению, ошибка компиляции не исчезла. –

+0

Чтобы получить неявное для работы, ему нужен этот путь: 'User -> UserDTO -> Writes [UserDTO]'.Но имплициты не так автоматически соединяются. Вам нужно явно преобразовать 'User' в' UserDTO', или немного помочь компилятору, указав тип присваивания: 'Json.toJson (elem: UserDTO)' –

+0

Большое спасибо, Alvaro. Я смог решить эту проблему, но затем компилятор начал жаловаться на 'пишет' ... Я обновляю код и вот ошибка:' Ошибка: (41, 24) Невозможно написать экземпляр Seq [play.api.libs. json.JsValue] для ответа HTTP. Попробуйте определить Writeable [Seq [play.api.libs.json.JsValue]] .map {list => Ok (list.map (elem => Json.toJson (elem: UserDto)))}. Миграция в scala действительно тяжелая .. –