Play Framework 2.2.1 Json Combinators — чтение и запись ошибки компиляции

Попытка запустить примеры Json Combinator для чтения и записи Json с 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, "[email protected]", ("alpha", 85), List(), Some("@gizmo"))
val gizmojs = Json.toJson(gizmo)

Ok(gizmojs toString)
}

Я получаю следующую ошибку компиляции:

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

У меня похожая проблема с Reads и Format.

Пожалуйста помоги.


person centr    schedule 01.01.2014    source источник
comment
Может быть, вы могли бы просто использовать Json.reads/Json.writes или Json.formats. Он будет генерировать те, которые используют макрос.   -  person jilen    schedule 01.01.2014


Ответы (2)


Вы совершенно правы, это не работает так, как задокументировано. Я думаю, что комбинаторы JSON в Play все еще находятся в постоянном развитии, поэтому документация, вероятно, страдает в результате.

Быстрое исправление: измените creatureWrites на def, и, таким образом, разрешена "прямая ссылка" (это рекурсивный вызов функции):

implicit def creatureWrites: Writes[Creature] = (
   ...
)
person millhouse    schedule 01.01.2014
comment
Спасибо. Простое быстрое решение, которое я искал. - person centr; 02.01.2014

Это потому, что вы определяете неявное значение как локальный элемент. Классы и объекты допускают прямые ссылки, а локальные блоки — нет.

Поэтому просто определите неявные операции чтения и записи как член класса, а не как локальный.

Посмотри на мой тест

Спецификация:

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, "[email protected]", ("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)
    }
  }
}

Результат:

[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

Вы можете легко определить чтение/запись, например

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]
person jilen    schedule 01.01.2014