Search code examples
jsonscalasprayspray-json

How do I turn all rejections into custom json in spray?


When spray (spray.io) produces a rejection, it responds with a string body. Since all my API clients will assume that my API only returns json, I'd like globally make every rejection a valid json object that conforms to our error object format. How can I make this happen?

The error object format looks like this

{
    'details' : 'Something happened in the app. boooo!',
    'errorType' : 'Unknown'
}

The errorType is my internal enum-style list of values like UserNotFound and NeedPaidAccount


Solution

  • If you just want to turn all of the rejections into your custom json format, you can create a rejection handler. For example, I'll put this in my ServiceActor and do the following:

    class ApiServiceActor extends Actor with HttpServiceActor with ApiServices {
      def jsonify(response: HttpResponse): HttpResponse = {
        response.withEntity(HttpBody(ContentType.`application/json`,
          JSONObject(Map(
            "details" -> response.entity.asString.toJson,
            "errorType" -> ApiErrorType.Unknown.toJson
          )).toString()))
      }
    
      implicit val apiRejectionHandler = RejectionHandler {
        case rejections => mapHttpResponse(jsonify) {
          RejectionHandler.Default(rejections)
        }
      }
    
      def receive = runRoute {
        yourRoute ~ yourOtherRoute ~ someOtherRoute
      }
    }