3

I try to serialize my models in a play 2.0 application with Scala to Json. This is how my code looks like:

package models

import play.api.libs.json._

case class Task(id: Long, label: String, date: String)

object Task {

  ...

  implicit object TaskFormat extends Format[Task] {
    def reads(json: JsValue): Task = Task(
      (json \ "id").as[Long],
      (json \ "label").as[String],
      (json \ "date").as[String])

    def writes(t: Task): JsValue = JsObject(Seq(
      "id" -> JsNumber(t.id),
      "label" -> JsString(t.label),
      "date" -> JsString(t.date)))
  }
}

Unfortunartly I get the following error when running the application:

verriding method reads in trait Reads of type (json: play.api.libs.json.JsValue)play.api.libs.json.JsResult[models.Task]; method reads has incompatible type

I didn't yet find a solution. The documentation of the api (http://www.playframework.org/documentation/api/2.0/scala/play/api/libs/json/package.html) seems to suggest the approach I've taken as well.

Does anybody spot my mistake?

Many thanks,
Joel

acjay
  • 34,571
  • 6
  • 57
  • 100
jokr
  • 242
  • 3
  • 13

2 Answers2

6

The error message tells you what the problem is: the return type must be

play.api.libs.json.JsResult[models.Task]

So it looks to me like you are returning the Task directly, not wrapping it in a JsResult.

I don't use Play, but this is what the compiler is trying to tell you.

So, given that, what is the issue? If you look at the Play 2.0 documentation, it says reads returns a T. But if you look at the GitHub source you find that it was changed to JsResult[T] as of August 21, 2012.

So you're using a newer version than the one people have written advice for.

I'm not sure whether the newer API is online, but you can browse the JSON source here.

Rex Kerr
  • 166,841
  • 26
  • 322
  • 407
  • Okay, maybe I really don't see it right now, but that doesn't help me much. I get what the compiler tells me, but I don't know how to return a `JsResult[Task]`. All the documentation on the web also seems to have the same code as I do (e.g. http://www.playframework.org/documentation/2.0.1/ScalaJsonGenerics, http://stackoverflow.com/questions/11979638/serializing-objects-to-json-with-play-api-libs-json). – jokr Dec 25 '12 at 22:00
  • @jomikr - Edited my answer, as I figured out what was going on. – Rex Kerr Dec 25 '12 at 22:37
  • 1
    Thanks for pointing that out. I did not imagine that they changed the api in such a way. Looking at the sources finally got me the solution: `def reads(json: JsValue) = JsSuccess(Task( (json \ "id").as[Long], (json \ "label").as[String], (json \ "date").as[String]))` – jokr Dec 26 '12 at 12:34
1

According to this post, a more correct way to implement Reads[T] in Play 2.1 would be:

implicit val productReads: Reads[Product] = (
    (__ \ "ean").read[Long] and
    (__ \ "name").read[String] and
    (__ \ "description").read[String]
)(Product.apply _)

And don't forget additional imports:

import play.api.libs.functional.syntax._ 
import play.api.libs.json._
dvim
  • 2,223
  • 1
  • 17
  • 17