0

我是scala新手,試圖理解它的基本概念。使用play/scala/slick我試圖實現簡單的應用程序,允許用戶對其他用戶執行CRUD操作。所以我面臨的問題是,我不明白我應該如何使用隱式轉換將模型對象轉換爲DTO對象。
這裏是我到目前爲止有:Scala將模型對象轉換爲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)未找到類型爲Application.this.userDAO.Entity的Json序列化程序。嘗試爲此類型實現隱式Writes或Format。 .map {list => Ok(list.map(elem => Json.toJson(elem)))}。我應該如何以及在哪裏實現從用戶到用戶的轉換,以便它可以工作而不是醜陋?

例如,在Java中我會實現每個Dto對象public User to()public static UserDto from(User user),以便我可以轉換它們。我應該在scala中做同樣的事情還是有更好的方法來完成這個任務?

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

看來,編譯器不看到userWriterUserDto對象。

+0

'用戶列表 .MAP {名單=> 好(userList.map(名單=> list.map(ELEM => Json.toJson(ELEM))))}'爲什麼你映射了'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 - >寫入[UserDTO]'。但隱含鏈不會自動鏈接。你需要顯式地將'User'轉換爲'UserDTO',或者通過提供一個類型歸類來幫助編譯器:'Json.toJson(elem:UserDTO)' –

+0

非常感謝,Alvaro。我能解決這個問題,但後來編譯器開始抱怨'寫道......我更新代碼,這裏是錯誤:'錯誤:(41,24)無法編寫一個Seq實例[play.api.libs。 json.JsValue]轉換爲HTTP響應。嘗試定義一個可寫[Seq [play.api.libs.json.JsValue]] .map {list => Ok(list.map(elem => Json.toJson(elem:UserDto)))}'。遷移到scala非常艱難.. –