0

スプレー JSON ライブラリを使用して、ケース クラスを JSON にシリアル化しています。問題は、相互に再帰的な定義があることです。私はここで封印された特性をシリアライズするための例から取り組んでいます: http://www.cakesolutions.net/teamblogs/2012/11/30/spray-json-and-adts/

これが機能する簡単な例です。C の定義に注意してください:

import spray.json._
import DefaultJsonProtocol._

sealed trait BaseTrait
sealed trait SpecializedTrait extends BaseTrait

case class A(argA: BaseTrait, foo: Int) extends SpecializedTrait
case class B(argB: BaseTrait, foo: Int) extends SpecializedTrait

case class C(foo: Int) extends BaseTrait

object BaseTrait {
  implicit val cJsonFormat = jsonFormat1(C)

  implicit object BaseTraitJsonFormat extends RootJsonFormat[BaseTrait] {
    override def write(obj: BaseTrait): JsValue = throw new IllegalStateException("Not Implemented")
    override def read(v: JsValue): BaseTrait = throw new IllegalStateException("Not Implemented")
  }
}

object SpecializedTrait {
  implicit val aJsonFormat = jsonFormat2(A)
  implicit val bJsonFormat = jsonFormat2(B)

  implicit object SpecializedTraitJsonFormat extends RootJsonFormat[SpecializedTrait] {
    override def write(obj: SpecializedTrait): JsValue = throw new IllegalStateException("Not Implemented")
    override def read(v: JsValue): SpecializedTrait = throw new IllegalStateException("Not Implemented")
  }
}

「C」の定義を元の相互再帰的な定義に変更すると、.

...
case class C(argC: SpecializedTrait, foo: Int) extends BaseTrait

object BaseTrait {
  implicit val cJsonFormat = jsonFormat2(C)

...

明らかに、ノーとは言えません。相互に再帰的なデータ構造を持つことはできません。暗黙的なオブジェクトの解決規則が原因で、コンパイラがつまずいているようです。

これに対する回避策はありますか? オブジェクトを匿名クラス宣言に変更することで回避しました。

import spray.json._
import DefaultJsonProtocol._

sealed trait BaseTrait
sealed trait SpecializedTrait extends BaseTrait

case class A(argA: BaseTrait, foo: Int) extends SpecializedTrait
case class B(argB: BaseTrait, foo: Int) extends SpecializedTrait

case class C(argC: SpecializedTrait, foo: Int) extends BaseTrait

object BaseTrait {
  implicit val cJsonFormat : RootJsonFormat[C] = jsonFormat2(C)

  implicit val baseTraitFormat : RootJsonFormat[BaseTrait] = new RootJsonFormat[BaseTrait] {
    def write(obj: BaseTrait): JsValue = throw new IllegalStateException("Not Implemented")
    def read(v: JsValue): BaseTrait = throw new IllegalStateException("Not Implemented")
  }
}

object SpecializedTrait {
  implicit val aJsonFormat : RootJsonFormat[A] = jsonFormat2(A)
  implicit val bJsonFormat : RootJsonFormat[B] = jsonFormat2(B)

  implicit val specializedTraitFormat : RootJsonFormat[SpecializedTrait] = new RootJsonFormat[SpecializedTrait] {
    override def write(obj: SpecializedTrait): JsValue = throw new IllegalStateException("Not Implemented")
    override def read(v: JsValue): SpecializedTrait = throw new IllegalStateException("Not Implemented")
  }
}

最後のスニペットは機能します。「implicit object」から「implicit val」への変更と、その後の匿名クラスに注意してください。

4

1 に答える 1

0

暗黙を順番に定義し、それらを 1 つのオブジェクトに入れます。

import spray.json._
import DefaultJsonProtocol._

sealed trait BaseTrait
sealed trait SpecializedTrait extends BaseTrait

case class A(argA: BaseTrait, foo: Int) extends SpecializedTrait
case class B(argB: BaseTrait, foo: Int) extends SpecializedTrait
case class C(argC: SpecializedTrait, foo: Int) extends BaseTrait

object SomeProtocol {
  implicit object BaseTraitJsonFormat extends RootJsonFormat[BaseTrait] {
    override def write(obj: BaseTrait): JsValue = throw new IllegalStateException("Not Implemented")
    override def read(v: JsValue): BaseTrait = throw new IllegalStateException("Not Implemented")
  }
  implicit object SpecializedTraitJsonFormat extends RootJsonFormat[SpecializedTrait] {
    override def write(obj: SpecializedTrait): JsValue = throw new IllegalStateException("Not Implemented")
    override def read(v: JsValue): SpecializedTrait = throw new IllegalStateException("Not Implemented")
  }
  implicit val aJsonFormat = jsonFormat2(A)
  implicit val bJsonFormat = jsonFormat2(B)
  implicit val cJsonFormat = jsonFormat2(C)
}
于 2014-03-25T23:49:21.783 に答える