我有以下代码,使用spray-json将一些JSON反序列化为一个case类,通过
根据隐式的JsonFormat[MyCaseClass]定义的位置(内联或从伴生对象导入),以及在定义时是否提供了显式类型,代码可能无法编译。
我不明白为什么从伴生对象导入隐式需要定义显式类型,但如果我把它放在内联中,则不需要。
有趣的是,IntelliJ在所有情况下都可以正确定位隐式参数(通过cmd-shift-p)。
我正在使用Scala 2.11.7。
错误代码 - 从伴生对象通配符导入,推断类型:
parseJson
方法实现。根据隐式的JsonFormat[MyCaseClass]定义的位置(内联或从伴生对象导入),以及在定义时是否提供了显式类型,代码可能无法编译。
我不明白为什么从伴生对象导入隐式需要定义显式类型,但如果我把它放在内联中,则不需要。
有趣的是,IntelliJ在所有情况下都可以正确定位隐式参数(通过cmd-shift-p)。
我正在使用Scala 2.11.7。
错误代码 - 从伴生对象通配符导入,推断类型:
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])
}