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._
// ...
}
希望对您有所帮助。
我正在尝试使用 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._
// ...
}
希望对您有所帮助。