简体   繁体   中英

Play Framework 2.2.1 Json Combinators - Reads and Writes Compile Error

Trying to run Json Combinator examples for Json Reads and Writes from http://www.playframework.com/documentation/2.2.x/ScalaJsonCombinators :

def test = Action {

case class Creature(name: String,isDead: Boolean,weight: Float, email: String, favorites: (String, Int), friends: List[Creature] = Nil, social: Option[String] = None)
import play.api.libs.json._
import play.api.libs.functional.syntax._

implicit val creatureWrites: Writes[Creature] = (
  (__ \ "name").write[String] and
    (__ \ "isDead").write[Boolean] and
    (__ \ "weight").write[Float] and
    (__ \ "email").write[String] and
    (__ \ "favorites").write(
      (__ \ "string").write[String] and
        (__ \ "number").write[Int]
        tupled
    ) and
    (__ \ "friends").lazyWrite(Writes.traversableWrites[Creature](creatureWrites)) and
    (__ \ "social").write[Option[String]]
  )(unlift(Creature.unapply))

val gizmo = Creature("gremlins", false, 1.0F, "gizmo@midnight.com", ("alpha", 85), List(), Some("@gizmo"))
val gizmojs = Json.toJson(gizmo)

Ok(gizmojs toString)
}

I receive the following compile error:

[error] ....:forward reference extends over definition of value creatureWrites
[error] (__ \ "friends").lazyWrite(Writes.traversableWrites[Creature](creatureWrites)) 

I have a similar problem with Reads and Format .

Please help.

That's because you are define the implicit value as local member . Classes and objects allow forward references, whereas local block do not

So just define the implicit reads and writes as class member , not local

Look at my test

The Spec:

import play.api.libs.json._
import play.api.libs.functional.syntax._
import org.specs2.mutable.Specification

case class Creature(
  name: String,
  isDead: Boolean,
  weight: Float,
  email: String,
  favorites: (String, Int),
  friends: List[Creature] = Nil,
  social: Option[String] = None)

class FooSpec extends Specification {
  implicit val creatureWrites: Writes[Creature] = (
    (__ \ "name").write[String] and
      (__ \ "isDead").write[Boolean] and
      (__ \ "weight").write[Float] and
      (__ \ "email").write[String] and
      (__ \ "favorites").write(
        (__ \ "string").write[String] and
          (__ \ "number").write[Int]
          tupled
      ) and
      (__ \ "friends").lazyWrite(Writes.traversableWrites[Creature](creatureWrites)) and
      (__ \ "social").write[Option[String]]
  )(unlift(Creature.unapply))
  implicit val favouriteReads: Reads[(String, Int)] =
    (__ \ "string").read[String]and
      (__ \ "number").read[Int] tupled
  implicit val creatureReads = Json.reads[Creature]

  val gizmo = Creature("gremlins", false, 1.0F, "gizmo@midnight.com", ("alpha", 85), List(), Some("@gizmo"))
  val gizmojs = Json.toJson(gizmo)
  "writes" should {
    "write scala value as string" in {
      Json.parse(gizmojs.toString).as[Creature] must be_==(gizmo)
    }
  }
}

Result:

[success] Total time: 10 s, completed Jan 1, 2014 11:25:25 PM
[ops-ui] $ testOnly FooSpec
[info] FooSpec
[info] writes should
[info] + write scala value as string
[info] Total for specification FooSpec
[info] Finished in 1 second, 813 ms
[info] 1 example, 0 failure, 0 error
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
[success] Total time: 6 s, completed Jan 1, 2014 11:25:45 PM

You could define reads/writes easily like

implicit val favouriteWrites =
    (__ \ "string").write[String] and
      (__ \ "number").write[Int] tupled
  implicit val creatureWrites: Writes[Creature] = Json.writes[Creature]

  implicit val favouriteReads: Reads[(String, Int)] =
    (__ \ "string").read[String]and
      (__ \ "number").read[Int] tupled
  implicit val creatureReads = Json.reads[Creature]

You're completely right, it doesn't work as documented. I think Play's JSON Combinators are still in a state of flux so the documentation is probably suffering as a result.

Quick fix: change creatureWrites to be a def , and thus the "forward reference" is allowed (it's a recursive function call):

implicit def creatureWrites: Writes[Creature] = (
   ...
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM