Json – How to serialize/deserialize case classes to/from Json in Play 2.1

jsonplayframework-2.0playframework-2.1scala

I'm trying to serialize/deserialize some case classes to/from Json… and I've troubles when dealing with case classes with just one field (I'm using Play 2.1):

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

case class MyType(type: String)

object MyType {

  implicit val myTypeJsonWrite = new Writes[MyType] {
    def writes(type: MyType): JsValue = {
      Json.obj(
        "type" -> MyType.type
      )
    }
  }

  implicit val myTypeJsonRead = (
    (__ \ 'type).read[String]
  )(MyType.apply _)
}

The code above always generates the following error message:

[error] /home/j3d/Projects/test/app/models/MyType.scala:34: overloaded method value read with alternatives:
[error]   (t: String)play.api.libs.json.Reads[String] <and>
[error]   (implicit r: play.api.libs.json.Reads[String])play.api.libs.json.Reads[String]
[error]  cannot be applied to (String => models.MyType)
[error]     (__ \ 'method).read[String]
[error]                        ^

I know… a case class that contains just a string does not make much sense… but I need to serialize/deserialize a case class very similar to the one I described above that comes from an external library.

Any idea? Am I missing something? Any help would be really appreciated… I'm getting crazy 🙁 Thanks.

Best Answer

Json combinators doesn't work for single field case class in Play 2.1 (it should be possible in 2.2)

Pascal (writer of this API) has explained this situation here https://groups.google.com/forum/?fromgroups=#!starred/play-framework/hGrveOkbJ6U

There are some workarounds which works, like this one:

case class MyType(value: String)
val myTypeRead = (__ \ 'value).read[String].map(v => MyType(v)) // covariant map

ps: type is a keyword in Scala, it can't be used as parameter name (but I assume it's just for this example)

edit: This workaround is not yet required with play 2.3.X. The macro works fine.