【发布时间】:2015-12-03 00:20:33
【问题描述】:
我有以下代码,它使用 spray-json 通过parseJson 方法将一些 JSON 反序列化为案例类。
取决于隐式 JsonFormat[MyCaseClass] 的定义位置(内联或从伴随对象导入),以及定义时是否提供了显式类型,代码可能无法编译。
我不明白为什么从伴随对象中导入隐式需要它在定义时具有显式类型,但如果我把它内联,就不是这样了吗?
有趣的是,IntelliJ 在所有情况下都能正确定位隐式参数(通过 cmd-shift-p)。
我使用的是 Scala 2.11.7。
Broken Code - 从伴随对象导入通配符,推断类型:
import SampleApp._
import spray.json._
class SampleApp {
import MyJsonProtocol._
val inputJson = """{"children":["a", "b", "c"]}"""
println(s"Deserialise: ${inputJson.parseJson.convertTo[MyCaseClass]}")
}
object SampleApp {
case class MyCaseClass(children: List[String])
object MyJsonProtocol extends DefaultJsonProtocol {
implicit val myCaseClassSchemaFormat = jsonFormat1(MyCaseClass)
}
}
结果:
Cannot find JsonReader or JsonFormat type class for SampleAppObject.MyCaseClass
请注意,显式导入 myCaseClassSchemaFormat 隐式也会发生同样的事情。
工作代码 #1 - 从伴随对象导入通配符,显式类型:
在伴生对象中向 JsonFormat 添加显式类型会导致代码编译:
import SampleApp._
import spray.json._
class SampleApp {
import MyJsonProtocol._
val inputJson = """{"children":["a", "b", "c"]}"""
println(s"Deserialise: ${inputJson.parseJson.convertTo[MyCaseClass]}")
}
object SampleApp {
case class MyCaseClass(children: List[String])
object MyJsonProtocol extends DefaultJsonProtocol {
//Explicit type added here now
implicit val myCaseClassSchemaFormat: JsonFormat[MyCaseClass] = jsonFormat1(MyCaseClass)
}
}
工作代码 #2 - 隐式内联,推断类型:
但是,将隐式参数放在使用它们的位置,没有显式类型,也可以!
import SampleApp._
import spray.json._
class SampleApp {
import DefaultJsonProtocol._
//Now in-line custom JsonFormat rather than imported
implicit val myCaseClassSchemaFormat = jsonFormat1(MyCaseClass)
val inputJson = """{"children":["a", "b", "c"]}"""
println(s"Deserialise: ${inputJson.parseJson.convertTo[MyCaseClass]}")
}
object SampleApp {
case class MyCaseClass(children: List[String])
}
【问题讨论】:
-
这是“当我这样做时很痛”的问题之一,其中最好的答案几乎肯定是“好吧,不要那样做”。以我的经验,缺少类型注释的隐式值是 Scala 中最常见的混淆、奇怪的跨版本行为差异等来源之一。
-
嗨,Travis - 确实,这是一个可以解决的有趣错误,但我想下次类型注释将是我解决类似问题的第一个停靠点!不确定这是否算作 Scala 错误,但可能会将某些内容放入邮件列表/查看提出问题以防万一。
-
编译器会吐出一条错误消息,说“隐式方法在此处不适用,因为它位于应用程序点之后,并且缺少显式结果类型”,因此至少该错误易于诊断和修复: )
-
呵呵,您是否使用以下任何代码示例收到类似的错误消息?我只收到粘贴的错误,
Cannot find JsonReader or JsonFormat type class for SampleAppObject.MyCaseClass,但你的会更有用。
标签: scala implicit spray spray-json