Scala 使用引用基类的子类为类层次结构喷涂json格式
我有一个表示过滤器类型的类层次结构,其中一个类型包含一个基类型列表。我不知道如何为这些类型设置spray json格式,因为基类型和包含类型的格式化程序需要相互引用 让我们从类层次结构和json格式开始,其中有问题的部分被注释掉:Scala 使用引用基类的子类为类层次结构喷涂json格式,scala,spray-json,Scala,Spray Json,我有一个表示过滤器类型的类层次结构,其中一个类型包含一个基类型列表。我不知道如何为这些类型设置spray json格式,因为基类型和包含类型的格式化程序需要相互引用 让我们从类层次结构和json格式开始,其中有问题的部分被注释掉: object Filters { sealed trait Filter case class SimpleFilter(foo: String) extends Filter case class DoubleFilter(foo: String, ba
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]
}
}
}
这编译和工作如预期,我可以序列化和反序列化具体的过滤器子类作为过滤器没有问题
但是让我们在和filter
中进行评论。现在有麻烦了!由于在filternformat
之前声明了和格式
(如上所述),它将不会编译,因为和格式
需要filternformat
:
错误:(17,43)找不到spray.json.DefaultJsonProtocol.JF[List[classpath.Filters.Filter]]类型的证据参数的隐式值
隐式val andFormat=jsonFormat1(AndFilter)
在filtermerformat
之后将顺序切换到和format
,这样可以编译内容。当然,我还想在write方法中添加和format
-引用子句到filter
格式,即case x:AndFilter=>x.toJson
,以及read方法中包括json.convertTo[AndFilter]
的任何内容。这也不会编译:
错误:(23,34)找不到classpath.Filters.Filter和classpath.Filters.AndFilter的JsonWriter或JsonFormat类型类
案例x:AndFilter=>x.toJson
我找不到任何办法来解决这个问题。我尝试过spray json的
lazyFormat
,但没有帮助(只适用于递归自引用,而不是像这样的交叉引用)。有什么想法吗?有时候你需要帮助编译器一点。在filtermerformat
上添加显式类型和显式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]
的隐式解析解决了这个问题
隐式val和格式:JsonFormat[AndFilter]=lazyFormat(jsonFormat1(AndFilter))
请注意,我们需要为和提供显式类型注释(即JsonFormat[AddFilter]
),以便SparyJsonSupport
可以将其作为RootJsonFormat
的实例,而不是lazyFormat
返回的JsonFormat
:
import spray.json_
导入DefaultJsonProtocol_
对象过滤器{
密封特性滤波器
case类SimpleFilter(foo:String)扩展了过滤器
case类DoubleFilter(foo:String,bar:String)扩展了过滤器
案例类和过滤器(过滤器:列表[Filter])扩展过滤器
隐式val simpleFormat=jsonFormat1(SimpleFilter)
隐式val doubleFormat=jsonFormat2(双过滤器)
隐式val andFormat:JsonFormat[AndFilter]=lazyFormat(jsonFormat1(AndFilter))
隐式val filtermerformat=new RootJsonFormat[Filter]{
覆盖def写入(obj:过滤器):JsValue=???
覆盖def读取(json:JsValue):过滤器=???
}
}
详情请参阅 哦。哼!(在我的辩护中,我已经建立了一个协议,并在几个层次结构中建立了几十个case类,但有点忘记了事情不必是隐式的。:))不幸的是,虽然这样编译,但它不起作用。尝试序列化和过滤器
会在spray.json.CollectionFormats
中抛出空指针异常,调用spray.json.PimpedAny.toJson
,其中隐式的JsonWriter
(应该是过滤器格式)为空。旁注-Pim复制的我的原始代码忽略了和Filter
扩展Filter
。我来编辑,太好了!当我最初使用它时,我曾尝试使用lazyFormat
,但可能没有显式类型注释?或者是其他一些用户错误——无论如何,我都无法让它工作。谢谢你的解决方案!