我正在使用spray,我试图表达异构JSON数组的概念 - 也就是说,一切都是JsonFormat
成员的数组。例如,scala值可能如下所示:
case class Dog(name: String, age: Int)
// not sure how to express this type
val json: [???] = List(3, "abc", List(), Dog("Rover", 3))
并且相应的JSON看起来像这样:
[3, "abc", {"qrs": 4}, [], {"name": "Rover", "age": 3}]
我已经标记了“存在感”和“类型类”的问题,因为我猜这是解决方案将涉及的内容(如果这是错误的话,我很乐意改变它)。我已经找到了一个解决方法,所以这篇文章的目的是为了弄清楚如何在Scala类型系统中表达它。
这会强制所有元素属于同一类型,而我正在尝试表达异构列表:
case class MyJson1[T](items: List[T])
object JsonProtocol extends DefaultJsonProtocol {
implicit def dogFormat = jsonFormat2(Dog)
implicit def format[T : JsonFormat] = jsonFormat1(MyJson1[T])
}
Any
不允许类型系统证明值是JsonFormat
的成员:
case class MyJson2(items: List[Any])
object JsonProtocol extends DefaultJsonProtocol {
implicit def dogFormat = jsonFormat2(Dog)
implicit val format = jsonFormat1(MyJson2)
}
_
(存在主义)存在同样的问题:编译器无法证明这些项是JsonFormat
的成员:
case class MyJson3(items: List[_])
object JsonProtocol extends DefaultJsonProtocol {
implicit def dogFormat = jsonFormat2(Dog)
implicit val format = jsonFormat1(MyJson3)
}
好吧,这只是一个疯狂的猜测而且不起作用:
case class MyJson4[T](items: List[T])
object JsonProtocol extends DefaultJsonProtocol {
implicit def dogFormat = jsonFormat2(Dog)
implicit def format[C <: JsonFormat[T] forSome { type T}] = jsonFormat1(MyJson4[C])
}
答案 0 :(得分:1)
我认为最好的方法是创建一个&#34;包装器&#34;它包含值和类型类实例。
class Wrapper[T](val value: T, val format: JsonFormat[T])
object Wrapper {
def apply[T](value: T)(implicit format: JsonFormat[T]) = new Wrapper(value, format)
}
val json: List[Wrapper[_]] = List(Wrapper(3), Wrapper("abc"), Wrapper(Dog("Rover", 3))
// or use an implicit conversion to wrapper
implicit def wrapValue[T: JsonFormat](value: T) = Wrapper(value)
// note that you *must* explicitly state the list type in order for the conversion to apply
val json: List[Wrapper[_]] = List(3, "abc", Dog("Rover", 3))
在执行以下操作时可能会遇到麻烦:
for(wrapper <- json) yield {
wrapper.format.doWhateverJsonFormatDoes(wrapper.value) // error
}
某种&#34;类型不匹配&#34;错误,但你可以通过定义一个&#34;包装器来解决这个问题。对于类型类方法,在Wrapper
类中:
class Wrapper[T](val value: T, val format: JsonFormat[T]){
def doWhateverJsonFormatDoes = format.doWhateverJsonFormatDoes(value)
}
for(wrapper <- json) yield wrapper.doWhateverJsonFormatDoes