Spray JSON 无法序列化 case class

Spray JSON can't serialise case class

我正在尝试使用 Spray 转换以下情况 class to/from JSON:

case class Interval(lower: Int, upper: Int)

这是通过以下方式实现的:

implicit val intervalFormat = jsonFormat2(Interval)

这可以编译,但会出现运行时错误:

Cannot automatically determine case class field names and order for 'Interval', please use the 'jsonFormat' overload with explicit field name specification

对该错误的搜索表明,它通常在子classes 声明附加字段时出现,而这里不是这种情况。

我是不是误以为Spray应该可以自动格式化区间class?

如果是这样,那么(正如错误消息所暗示的那样)我是否应该为格式化程序提供有关 Interval 字段的更明确的信息?如何最容易实现这一目标?

编辑:@retrospectacus 的回答提供了一些有用的观点,但其中 none 解决了问题。我采用的解决方法是提供字段类型和名称的明确描述:

implicit val intervalFormat = jsonFormat[Int, Int,Interval](Interval, "lower", "upper")

这行得通,但我将问题悬而未决,因为仍然不清楚为什么这是必要的。

此错误的常见原因:

  • 如果你在某处有 case object Interval(伙伴),那么 jsonFormat 应该像 jsonFormat2(Interval.apply) 一样创建。
  • 向格式添加类型注释可以帮助:implicit val intervalFormat: RootJsonFormat[Interval] = ...
  • 您的 Interval class 可能会与另一个 Interval class 混淆,可能 org.joda.time.Interval,无论是在 jsonFormat 创建中还是在大小写的位置class 创建或序列化 - 您可以添加前缀或修复导入以避免这种情况。

希望这对您有所帮助。

编辑:我刚刚遇到的这个问题的另一个原因是,如果您在案例 class 中声明了任何 val,序列化程序将获胜'能够自动生成格式。例如

case class Interval(from: Int, to: Int) {
  val size: Int = to - from
}

错误将是 "java.lang.RuntimeException: Case class Interval declares additional fields"。

这可以使用如上所述的 jsonFormat 重载来解决,或者 val 可以简单地更改为 def.

对于在 class 中定义的案例 class,我遇到了同样的错误。例如

class TestClass {
  case class TestModel(a: String, b: Int, c: Long)

  trait TestJsonProtocol extends DefaultJsonProtocol {
    implicit def testJf: RootJsonFormat[TestModel] = jsonFormat3(TestModel.apply)
  }

// ...

}

编译时出错java.lang.RuntimeException: Cannot automatically determine case class field names and order for 'TestClass$TestModel', please use the 'jsonFormat' overload with explicit field name specification

将 TestModel 移动到 TestClass 伴随对象后问题就解决了:

object TestClass {
  case class TestModel(a: String, b: Int, c: Long)

  trait TestJsonProtocol extends DefaultJsonProtocol {
    implicit def testJf: RootJsonFormat[TestModel] = jsonFormat3(TestModel.apply)
  }
}

class TestClass {
  import TestClass._
  // ...
}

希望对您有所帮助。