我在Scala中有一个案例类
case class Employee(designation: Int, name: String)
现在我想在Spray中为其定义JSON格式。
据我所知,有两种方法。
implicit lazy val employeeProtocol: RootJsonFormat[Employee] =
jsonFormat2(Employee.apply)
或
implicit lazy val employeeProtocol: RootJsonFormat[Employee] =
jsonFormat(Employee, "designation", "name")
以上哪个是更好的方法?它们之间在性能方面有区别吗?
答案 0 :(得分:1)
当然,这里需要权衡。
您是否有用于JSON值的架构(显式或隐式)?如果是这样,那么对象键是否不同于案例类成员名?如果您对这两个问题的回答均为“是”,那么您将无法使用更明确的jsonFormat
版本。如果您对第一个问题的回答是“是”,但是第二个问题的回答是“否”,那么您可能仍想使用更明确的版本,因为它的魔力要少一些。
尽管有充分的理由偏爱jsonFormat2(Employee.apply)
版本。假设您有其他版本:
import spray.json._, DefaultJsonProtocol._
case class Employee(designation: Int, name: String)
implicit lazy val employeeProtocol: RootJsonFormat[Employee] =
jsonFormat(Employee, "designation", "name")
...然后下个月有人来重构案例类,但没有注意到实例:
case class Employee(name: String, designation: Int)
implicit lazy val employeeProtocol: RootJsonFormat[Employee] =
jsonFormat(Employee, "designation", "name")
恭喜:您有一个程序可以很好地编译,但是以可能非常混乱的方式失败。
或者,您可能只是不在乎JSON的样子,并且不想在两个地方都维护成员名称。在这两种情况下,面对重构,更简洁的jsonFormat
版本都会更强大。
就性能而言,这两个版本实际上是相同的,实际上jsonFormat2
仅在使用运行时反射从目标类型中提取成员名称后才调用jsonFormat
。尽管此运行时反射确实要付出(微小的)代价,但提取仅会在程序执行中执行一次(假设您使用val
或lazy val
来定义实例) ,并且在实际解码JSON时,两者的性能完全相同。