使用Play Framework序列化程序在Scala中将扩展类序列化为JSON

时间:2016-06-24 10:57:54

标签: json scala serialization playframework

我想在scala中序列化扩展类 我有一些测试代码..

import org.specs2.mutable._
import org.specs2.runner._
import org.junit.runner._
import play.api.libs.json.Json

@RunWith(classOf[JUnitRunner])
class JsonSerializerTest extends Specification {

  class A(val s1: String)
  case class B(s2: String) extends A("a")

  "Application" should {
    "serialize class to JSON" in {
      implicit val bWrites = Json.writes[B]
      implicit val bReads = Json.reads[B]

      val bClass = B("b")
      println(bClass.s1 + " " + bClass.s2)

      val serialized = Json.toJson[B](bClass)

      val s1 = (serialized \ "s1").asOpt[String]

      s1 should beSome[String]

    }
  }
}

在这种情况下测试打印:

a b
Application should

'None' is not Some
java.lang.Exception: 'None' is not Some

这意味着来自父类的s1字段未被序列化。

解决方案

class A(val s1: String)
case class B(override val s1: String, s2: String) extends A(s1)

主要是不可接受的,因为在实际应用程序类中有很多字段,并且每当我扩展类使代码复杂化时都会明确指定它们。

这种情况还有其他解决办法吗?

1 个答案:

答案 0 :(得分:0)

您可以手动创建json序列化程序(在此处描述:https://www.playframework.com/documentation/2.5.x/ScalaJsonCombinators

您的版本的问题是from rq.decorators import job @job('low', connection=my_redis_conn, timeout=600) def long_running_task(x, y): # Code Json.writes是专门查看Json.reads的构造函数的宏,并从中构建序列化程序(所以超类参数是'n'抓住)。您可以复制并滚动自己的宏版本:https://github.com/playframework/playframework/blob/d6c2673d91d85fd37de424951ee5ad9f4f4cce98/framework/src/play-json/src/main/scala/play/api/libs/json/JsMacroImpl.scala

最后,您可以创建一个取case classJson.writes结果的函数,并添加所需的共享字段。类似的东西:

Json.reads

取决于object A { def writesSubclass[T](writer: Writes[T]): Writes[T] = new Writes[T] { def writes(t: T) = Json.obj("s1" -> t.s1) ++ writer.writes(t).as[JsObject] } } implicit val bWrites = A.writesSubclass(Json.writes[B]) 延长的频率,这可能是您最好的选择。