簡體   English   中英

Scala-播放JSON特征序列化

[英]Scala - play json trait serialisation

在scala中,我定義了以下特征和類(名稱僅用於說明目的):

trait Entity {
  def x() : Collection
}

case class X(x : Int, y : Int) extends Entity {
  def x() : Collection = XCollection()
}

case class Y(x : Int, y : Int) extends Entity {
  def x() : Collection = YCollection()
}

通過解析來自Web服務REST API的響應來創建類實例。

盡管使用play-json庫的方法在解析響應並返回響應的類表示的情況下可行,但我一直在努力以下工作:具有帶類型參數的泛型函數,而T:Entity和返回類型T的實例。

例如,考慮以下內容:

def parse[T <: Entity](json : String) : Option[T] = Json.parse(json).asOpt[T](Variants.format[T])

給定類型T,我想解析JSON字符串並產生類型T的實例,而該實例是特征Entity的派生。 但是,關於反射API,我一直遇到編譯錯誤:

Error:(25, 96) exception during macro expansion: 
scala.ScalaReflectionException: type T is not a class
at scala.reflect.api.Symbols$SymbolApi$class.asClass(Symbols.scala:323)
at scala.reflect.internal.Symbols$SymbolContextApiImpl.asClass(Symbols.scala:73)
at julienrf.variants.Variants$Impl$.baseAndVariants(Variants.scala:132)
at julienrf.variants.Variants$Impl$.formatDiscriminator(Variants.scala:99)
at julienrf.variants.Variants$Impl$.format(Variants.scala:94)
def parse[T <: Entity](json : String) : Option[T] =     Json.parse(json).asOpt[T](Variants.format[T])
                                                                                           ^

因此,感謝您的幫助!

謝謝

與使用某種工廠相比,最好讓隱式解決您的格式要求:

def parse[T <: Entity](json: String)(implicit r: Reads[T]): Option[T] = 
     Json.parse(json).asOpt[T]

然后,如果您在當前上下文中隱式定義了一種格式,則parse將起作用:

implicit val XFormat = Json.format[X]

parse[X](Json.stringify(Json.toJson(X(1, 2))) // returns X(1, 2)

更新

如果確實需要,可以將其作為工廠。 我會問這樣做是否值得,但從理論上講,我可以想象一些不希望使用隱式機制的獨特情況。 我仍然認為,如果隱式對您不起作用,那么您的代碼中可能會存在體系結構問題

  import play.api.libs.json.{Json, Reads}

  import scala.reflect.runtime.universe._

  trait Entity
  case class X(x : Int, y : Int) extends Entity
  case class Y(x : Int, y : Int) extends Entity


  val mapping = Map[Type, Reads[_]](typeOf[X] -> Json.format[X], typeOf[Y] -> Json.format[Y])
  def getFormat[T](tpe: Type): Reads[T] =
    mapping(tpe).asInstanceOf[Reads[T]]

  def parse[T : TypeTag](json: String): Option[T] = {
    val map = mapping(implicitly[TypeTag[T]].tpe)
    Json.parse(json).asOpt[T](getFormat(implicitly[TypeTag[T]].tpe))
  }

  println(parse[X]("""{"x": 5, "y": 6}"""))
  println(parse[Y]("""{"x": 5, "y": 6}"""))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM