I am attempting to convert the following case class to/from JSON using Spray:
case class Interval(lower: Int, upper: Int)
This is achieved via:
implicit val intervalFormat = jsonFormat2(Interval)
This compiles, but gives the runtime error:
Cannot automatically determine case class field names and order for 'Interval', please use the 'jsonFormat' overload with explicit field name specification
A search on this error suggests that it typically arises when subclasses declare additional fields, which is not the case here.
Am I mistaken in thinking that Spray should be able to automatically format the interval class?
If so, then (as the error message appears to suggest) should I be providing a formatter with more explicit information about the fields of Interval? How might this most readily be achieved?
EDIT: The answer by @retrospectacus offers some helpful points, but none of them solve the problem. The workaround I adopted was to provide an explicit description of the types and names of the fields:
implicit val intervalFormat = jsonFormat[Int, Int,Interval](Interval, "lower", "upper")
This works, but I'm leaving the question open, since it's still not clear why this is necessary.
Common reasons for this error:
case object Interval
(companion) somewhere, then the jsonFormat should be created like jsonFormat2(Interval.apply)
.implicit val intervalFormat: RootJsonFormat[Interval] = ...
Interval
class could be confused with another Interval
class, possibly org.joda.time.Interval
, either in the jsonFormat creation or in the place of case class creation or serialization - you may add a prefix or fix imports to avoid this.Hope this helps.
EDIT: Another reason for this issue which I just encountered, is if you have any val
declared within the case class, the serializer won't be able to automatically generate a format. E.g.
case class Interval(from: Int, to: Int) {
val size: Int = to - from
}
The error will be "java.lang.RuntimeException: Case class Interval declares additional fields".
This can be solved using the jsonFormat
overload as described above, or the val
can be simply changed to a def
.