Pergunta

I am a play beginner and try to migrate my web application from Play 2.0.4 to the new shiny Play 2.1-RC2. My code doesn't compile because of the new JSON handling.

I have read Mandubians Blog, the Play 2.1 Migration guide and the Play JSON library documentation (beta) but I am still unsure what's the best way to migrate my code.

F.ex. I have a model called File with an implicit Read-Object (Play 2.0):

object File {
    implicit object FileReads extends Reads[File] {
      def reads(json: JsValue) = File(
        (json \ "name").as[String],
        (json \ "size").as[Long]
     )
   }
}

I use it like this in the controller (Play 2.0):

val file = webserviceResult.json.as[models.File]

The Play 2.1 Migration guide tells me to refactor it with a JsSuccess() like this (Play 2.1?):

object File {
    implicit object FileFormat extends Format[File] {
      def reads(json: JsValue) = JsSuccess(File(
        (json \ "name").as[String],
        (json \ "size").as[Long]
     ))
   }
}

But how can I use this implicit conversion now?

Or is it better to use the implicit val-stuff like in the Twitter-example from the Play for Scala-book? Whats the best way to convert a JsValue to it's Scala value?

Foi útil?

Solução

Or is it better to use the implicit val-stuff like in the Twitter-example from the Play for Scala-book?

Yes, for a classic conversion, it's a good solution (simple and concise).

But there is a simpler way to achieve this conversion with the "Json Macro Inception" :

import play.api.libs.json._
import play.api.libs.functional.syntax._

case class File(name: String, size: Long)
implicit val fileFormat = Json.format[File]

val json = Json.parse("""{"name":"myfile.avi", "size":12345}""") // Your WS result

scala> json.as[File]
res2: File = File(myfile.avi,12345)

Warning: You cannot put your formater in the companion object, it's a limitation of the current Json API.

I advice to use an object with all you json formatters, and to import it when necessary.

FYI, the raw formater should be written like this:

implicit val rawFileRead: Format[File] = ( 
    (__ \ "name").format[String] and 
    (__ \ "size").format[Long]
)(File.apply _, unlift(File.unapply _)) // or (File, unlift(File.unapply))

Check these two test class, there are many interesting exemples:

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top