class 层次结构的 Spray-json 格式,子class 引用基础 class
Spray-json formats for class hierarchy with subclass that references base class
我有一个代表过滤器类型的 class 层次结构,其中一个类型包含一个基本类型列表。我不知道如何为这些类型设置 spray-json 格式,因为基本类型和包含类型的格式化程序需要相互引用。
让我们从 class 层次结构和 json 格式开始,其中有问题的部分被注释掉了:
object Filters {
sealed trait Filter
case class SimpleFilter(foo: String) extends Filter
case class DoubleFilter(foo: String, bar: String) extends Filter
implicit val simpleFormat = jsonFormat1(SimpleFilter)
implicit val doubleFormat = jsonFormat2(DoubleFilter)
// case class AndFilter(filters: List[Filter]) extends Filter
// implicit val andFormat = lazyFormat(jsonFormat1(AndFilter))
// (would really use a type field, keeping simple for example)
implicit val filterFormat = new RootJsonFormat[Filter] {
override def write(obj: Filter): JsValue = obj match {
case x: SimpleFilter => x.toJson
case x: DoubleFilter => x.toJson
// case x: AndFilter => x.toJson
}
override def read(json: JsValue): Filter = json.asJsObject.getFields("bar") match {
case Seq(_) => json.convertTo[DoubleFilter]
case Seq() => json.convertTo[SimpleFilter]
}
}
}
这可以按预期编译和工作,我可以将具体的过滤器子 class 序列化和反序列化为过滤器没问题。
但让我们在 AndFilter
内容中发表评论。现在有麻烦了!在 filterFormat
之前声明 andFormat
(如上所述),它不会编译,因为 andFormat
需要 filterFormat
:
Error:(17, 43) could not find implicit value for evidence parameter of type spray.json.DefaultJsonProtocol.JF[List[classpath.Filters.Filter]]
implicit val andFormat = jsonFormat1(AndFilter)
在 filterFormat
之后将顺序切换到 andFormat
将使事情编译。但当然我也想将 andFormat
-referencing 子句添加到 filter
格式,即写入方法中的 case x: AndFilter => x.toJson
以及读取方法中包含 json.convertTo[AndFilter]
的任何内容。那也不编译:
Error:(23, 34) Cannot find JsonWriter or JsonFormat type class for classpath.Filters.Filter with classpath.Filters.AndFilter
case x: AndFilter => x.toJson
我找不到解决这个问题的方法。我试过 spray-json 的 lazyFormat
但它没有帮助(只适用于递归自引用,而不是像这样的交叉引用)。有什么想法吗?
有时您需要稍微帮助一下编译器。在 filterFormat
上添加显式类型和显式 write
将使其编译。
sealed trait Filter
case class SimpleFilter(foo: String) extends Filter
case class DoubleFilter(foo: String, bar: String) extends Filter
case class AndFilter(filters: List[Filter])
implicit val simpleFormat = jsonFormat1(SimpleFilter)
implicit val doubleFormat = jsonFormat2(DoubleFilter)
implicit val andFormat = jsonFormat1(AndFilter)
implicit val filterFormat: RootJsonFormat[Filter] = new RootJsonFormat[Filter] {
override def write(obj: Filter): JsValue = obj match {
case x: SimpleFilter => x.toJson
case x: DoubleFilter => x.toJson
case x: AndFilter => andFormat.write(x)
}
override def read(json: JsValue): Filter = json.asJsObject.getFields("bar") match {
case Seq(_) => json.convertTo[DoubleFilter]
case Seq() => json.convertTo[SimpleFilter]
}
}
我相信以下修改解决了问题中所述的隐式解析 JsonFormat[AndFilter]
的问题。
implicit val andFormat: JsonFormat[AndFilter] = lazyFormat(jsonFormat1(AndFilter))
请注意,我们需要为 andFormat
提供显式类型注释(即 JsonFormat[AddFilter]
),以便 SparyJsonSupport
可以将其作为 [=16= 的实例],而不是 lazyFormat
:
返回的 JsonFormat
import spray.json._
import DefaultJsonProtocol._
object Filters {
sealed trait Filter
case class SimpleFilter(foo: String) extends Filter
case class DoubleFilter(foo: String, bar: String) extends Filter
case class AndFilter(filters: List[Filter]) extends Filter
implicit val simpleFormat = jsonFormat1(SimpleFilter)
implicit val doubleFormat = jsonFormat2(DoubleFilter)
implicit val andFormat: JsonFormat[AndFilter] = lazyFormat(jsonFormat1(AndFilter))
implicit val filterFormat = new RootJsonFormat[Filter] {
override def write(obj: Filter): JsValue = ???
override def read(json: JsValue): Filter = ???
}
}
详情请见https://github.com/spray/spray-json#jsonformats-for-recursive-types。
我有一个代表过滤器类型的 class 层次结构,其中一个类型包含一个基本类型列表。我不知道如何为这些类型设置 spray-json 格式,因为基本类型和包含类型的格式化程序需要相互引用。
让我们从 class 层次结构和 json 格式开始,其中有问题的部分被注释掉了:
object Filters {
sealed trait Filter
case class SimpleFilter(foo: String) extends Filter
case class DoubleFilter(foo: String, bar: String) extends Filter
implicit val simpleFormat = jsonFormat1(SimpleFilter)
implicit val doubleFormat = jsonFormat2(DoubleFilter)
// case class AndFilter(filters: List[Filter]) extends Filter
// implicit val andFormat = lazyFormat(jsonFormat1(AndFilter))
// (would really use a type field, keeping simple for example)
implicit val filterFormat = new RootJsonFormat[Filter] {
override def write(obj: Filter): JsValue = obj match {
case x: SimpleFilter => x.toJson
case x: DoubleFilter => x.toJson
// case x: AndFilter => x.toJson
}
override def read(json: JsValue): Filter = json.asJsObject.getFields("bar") match {
case Seq(_) => json.convertTo[DoubleFilter]
case Seq() => json.convertTo[SimpleFilter]
}
}
}
这可以按预期编译和工作,我可以将具体的过滤器子 class 序列化和反序列化为过滤器没问题。
但让我们在 AndFilter
内容中发表评论。现在有麻烦了!在 filterFormat
之前声明 andFormat
(如上所述),它不会编译,因为 andFormat
需要 filterFormat
:
Error:(17, 43) could not find implicit value for evidence parameter of type spray.json.DefaultJsonProtocol.JF[List[classpath.Filters.Filter]] implicit val andFormat = jsonFormat1(AndFilter)
在 filterFormat
之后将顺序切换到 andFormat
将使事情编译。但当然我也想将 andFormat
-referencing 子句添加到 filter
格式,即写入方法中的 case x: AndFilter => x.toJson
以及读取方法中包含 json.convertTo[AndFilter]
的任何内容。那也不编译:
Error:(23, 34) Cannot find JsonWriter or JsonFormat type class for classpath.Filters.Filter with classpath.Filters.AndFilter case x: AndFilter => x.toJson
我找不到解决这个问题的方法。我试过 spray-json 的 lazyFormat
但它没有帮助(只适用于递归自引用,而不是像这样的交叉引用)。有什么想法吗?
有时您需要稍微帮助一下编译器。在 filterFormat
上添加显式类型和显式 write
将使其编译。
sealed trait Filter
case class SimpleFilter(foo: String) extends Filter
case class DoubleFilter(foo: String, bar: String) extends Filter
case class AndFilter(filters: List[Filter])
implicit val simpleFormat = jsonFormat1(SimpleFilter)
implicit val doubleFormat = jsonFormat2(DoubleFilter)
implicit val andFormat = jsonFormat1(AndFilter)
implicit val filterFormat: RootJsonFormat[Filter] = new RootJsonFormat[Filter] {
override def write(obj: Filter): JsValue = obj match {
case x: SimpleFilter => x.toJson
case x: DoubleFilter => x.toJson
case x: AndFilter => andFormat.write(x)
}
override def read(json: JsValue): Filter = json.asJsObject.getFields("bar") match {
case Seq(_) => json.convertTo[DoubleFilter]
case Seq() => json.convertTo[SimpleFilter]
}
}
我相信以下修改解决了问题中所述的隐式解析 JsonFormat[AndFilter]
的问题。
implicit val andFormat: JsonFormat[AndFilter] = lazyFormat(jsonFormat1(AndFilter))
请注意,我们需要为 andFormat
提供显式类型注释(即 JsonFormat[AddFilter]
),以便 SparyJsonSupport
可以将其作为 [=16= 的实例],而不是 lazyFormat
:
JsonFormat
import spray.json._
import DefaultJsonProtocol._
object Filters {
sealed trait Filter
case class SimpleFilter(foo: String) extends Filter
case class DoubleFilter(foo: String, bar: String) extends Filter
case class AndFilter(filters: List[Filter]) extends Filter
implicit val simpleFormat = jsonFormat1(SimpleFilter)
implicit val doubleFormat = jsonFormat2(DoubleFilter)
implicit val andFormat: JsonFormat[AndFilter] = lazyFormat(jsonFormat1(AndFilter))
implicit val filterFormat = new RootJsonFormat[Filter] {
override def write(obj: Filter): JsValue = ???
override def read(json: JsValue): Filter = ???
}
}
详情请见https://github.com/spray/spray-json#jsonformats-for-recursive-types。