我正在研究spray-json示例,最后一行val color = json.convertTo[Color]
有一个函数调用,它指定了类型类型?几乎看起来像将类型定义分配给常量。在这种情况下,有人可以解释那里发生了什么吗?
case class Color(name: String, red: Int, green: Int, blue: Int)
object MyJsonProtocol extends DefaultJsonProtocol {
implicit val colorFormat = jsonFormat4(Color)
}
import MyJsonProtocol._
import spray.json._
val json = Color("CadetBlue", 95, 158, 160).toJson
val color = json.convertTo[Color]
由于
答案 0 :(得分:3)
目前尚不清楚到底有什么不清楚。您json
变量的类型为JsValue
。该类具有指定为
convertTo
方法
def convertTo[T :JsonReader]: T = jsonReader[T].read(this)
此代码表示可以为任何类型convertTo
调用T
,在上下文中可以看到类型为JsonReader[T]
的隐式对象。所以这与一些编译魔术实际上是与
def convertTo[T](implicit jsonReader: JsonReader[T]): T = jsonReader.read(this)
那么这个诀窍究竟是什么呢?请考虑您是Spray JSON库的作者。显然,有许多类型无法从JSON中合理解码(例如,解码Thread
究竟是什么意思?)。因此,您希望JsValue.convertTo
方法成为"类型安全"在某种意义上,您只允许解码至少可能在理论上解码的类型。不幸的是,自动决定这100%是一项相当艰巨的任务。 Still Spray JSON(以及许多其他Scala JSON库)提供了一些近似值。我们的想法是,您声明了一个type class JsonReader[T]
,它正好对此属性进行编码 - 类型T
可以从JSON解码。然后,您需要仅解码为类型类成员的那些类型。 Scala中的这种类型类通常使用implicits来实现,即您不会强制显式传递证据,而是依赖于编译器来查找证据。 Althoug经常编译器只能通过上下文推断出正确的泛型类型替换,在这种特殊情况下没有上下文,所以你必须明确指定类型。
注意行
implicit val colorFormat = jsonFormat4(Color)
使用另一个强大的Scala技巧:宏。 Spray JSON提供了一个宏库,可以自动为多种类型生成类型类证据。