Accepted answer

After digging further, it seems the root of the problem has been a confusion of the Json4s and Spray-Json libraries in the code. In trying to track down examples of various elements of JSON handling, I didn't recognize the separation between the two libraries readily and ended up with code that mixed some of each, explaining the unexpected behavior.

In this question, the offending piece is pulling in the Json4sSupport in the router. The proper definition should be using SprayJsonSupport:

import MyJsonProtocol._

trait TestRoute extends HttpService with SprayJsonSupport {
  path("testRoute") {
    val response: Record = getErrorRecord()

With this all considered, the answers are more apparent.

1: Why does the serialization of Record fail to call the ErrorJsonFormat write method (what does it even do instead)?.

No JsonFormat is called because complete marshals via some other means. That other means is the marshaling provided implicitly by Json4s with Json4sSupport. You can use record.toJson to force spray-json serialization of the object, but the output will not be clean (it will include nested JS objects and "fields" keys).

  1. Is there a way to match my expectation while still using complete(record)?

Yes, using SprayJsonSupport will use implicit RootJsonReader and/or RootJsonWriter where needed to automatically create a relevant Unmarshaller and/or Marshaller. Documentation reference

So with SprayJsonSupport it will see the RootJsonWriter defined by the jsonFormat3(Record) and complete(record) will serialize as expected.

Related Query

More Query from same tag