2014-09-06 74 views
1

我使用的播放2.3.4,我已經定義了一個簡單的模型類爲:Json隱式讀取:類型不匹配?

case class User(
    @Id 
    id: Int, 
    name: String 
) extends Model 

object User { 
    def find() = { /* some code here */} 
    implicit object UserFormat extends Format[User] { 
    def reads(json: JsValue) = User(
     (json \ "id").as[Int], 
     (json \ "name").as[String] 
    ) 

    def writes(user: User) = JsObject(Seq("id" -> id, "name" -> name)) 
    } 
} 

這是非常簡單的。但我得到一個編譯錯誤:

Error:(31, -1) Play 2 Compiler: 
/Users/asheshambasta/code/finit/app/models/users/User.scala:31: type mismatch; 
    found : models.devices.User 
    required: play.api.libs.json.JsResult[models.users.User] 

我做錯了什麼?

回答

2

上面的代碼有幾個問題。您收到的編譯錯誤是因爲reads(json: JsValue)應返回JsResult而不是該模型。這是因爲在定義Reads時需要考慮失敗。 idname也需要是user.iduser.namewrites。這將編譯:

object User { 

    implicit object UserFormat extends Format[User] { 
     def reads(json: JsValue) = JsSuccess(User(
      (json \ "id").as[Int], 
      (json \ "name").as[String] 
     )) 

     def writes(user: User) = Json.obj("id" -> user.id, "name" -> user.name) 
    } 
} 

但是,如果沒有在JSON的錯誤,因爲as[T]是不是安全的,這將引發異常。

scala> val testJs = Json.parse("""{"id":"2", "name": "test"}""") 
testJs: play.api.libs.json.JsValue = {"id":"2","name":"test"} 

scala> testJs.validate[User] 
play.api.libs.json.JsResultException: JsResultException(errors:List((,List(ValidationError(error.expected.jsnumber,WrappedArray()))))) 

定義Reads這種方式對於簡單的對象幾乎都是不值得的,並且可以更好的實現使用JSON組合程序。

object User { 
    implicit val reads: Reads[User] = (
     (__ \ "id").read[Int] and 
     (__ \ "name").read[String] 
    ) 

    implicit val writes: Writes[User] = (
     (__ \ "id").write[Int] and 
     (__ \ "name").write[String] 
    )  
} 

JSON組合算符不會拋出異常喜歡代碼的第一個片段,並驗證時,他們會積聚所有的錯誤到JsResult。在簡單的情況就是這樣,JSON成立以來就更好了:

object User { 
    implicit val format: Format[User] = Json.format[User] 
} 

還有一些情況下,你需要一些定製的Reads但不Writes或周圍的其他方式Json.reads[T]Json.writes[T]宏。

+0

很好的答案,非常感謝。它解決了我的問題,也有助於使事情變得更清晰。 – Ashesh 2014-09-07 12:09:15