firemonkey
firemonkey

Reputation: 329

scala Spray Rest API return Json content type with RequestContext

My spray rest service invokes other actors(passing RequestContext in constructor) to perform business logic(similar to this approach). I have a use case where I need to read json text from a file and return the content. I want the content type to be JSON. How do I set content type to json explictly with requestcontext.

In the code snippet below requestContext needs to return string(Json) with Json content type. requestContext.complete("{\"name\":\"John\"}")

package com.christophergagne.sprayapidemo

import akka.actor.{Actor, ActorRef}
import akka.event.Logging
import akka.io.IO

import spray.routing.RequestContext
import spray.httpx.SprayJsonSupport
import spray.client.pipelining._

import scala.util.{ Success, Failure }

object TimezoneService {
  case class Process(long: Double, lat: Double, timestamp: String)
}

class TimezoneService(requestContext: RequestContext) extends Actor {

  import TimezoneService._

  implicit val system = context.system
  import system.dispatcher
  val log = Logging(system, getClass)

  def receive = {
    case Process(long,lat,timestamp) =>
      process(long,lat,timestamp)
      context.stop(self)
  }

  def process(long: Double, lat: Double, timestamp: String) = { 

    log.info("Requesting timezone long: {}, lat: {}, timestamp: {}", long, lat, timestamp)

    import TimezoneJsonProtocol._
    import SprayJsonSupport._
    val pipeline = sendReceive ~> unmarshal[GoogleTimezoneApiResult[Timezone]]

    val responseFuture = pipeline {
      Get(s"https://maps.googleapis.com/maps/api/timezone/json?location=$long,$lat&timestamp=$timestamp&sensor=false")
    }
    responseFuture onComplete {
      case Success(GoogleTimezoneApiResult(_, _, timeZoneName)) =>
        log.info("The timezone is: {} m", timeZoneName)
        ***requestContext.complete("{\"name\":\"John\"}")***

      case Failure(error) =>
        requestContext.complete(error)
    }
  }
}

thank you for help.

Upvotes: 0

Views: 557

Answers (2)

Martijn
Martijn

Reputation: 2326

You need to return a full HttpResponse object instead of a simple string. I recommend you do this:

import spray.routing.RequestContext
import spray.http._

requestContext.complete(HttpResponse(StatusCodes.OK, HttpEntity(ContentType(MediaTypes.`application/json`), "{\"name\":\"John\"}")))

You could also return only the HttpEntity since it has a defined ToResponseMarshaller which can be found here. Use it like so:

import spray.routing.RequestContext
import spray.http._

requestContext.complete(HttpEntity(ContentType(MediaTypes.`application/json`), "{\"name\":\"John\"}"))

I don't recommend you use string interpolation to return your JSON since this makes it hard to change the response structure. I recommend you use the spray-json library which already has a ToReponseMarshaller defined which can be found here. The functionality is documented here. Your code would look something like this:

import spray.routing.RequestContext
import spray.httpx.marshalling._
import spray.json._
import spray.httpx.SprayJsonSupport._

requestContext.complete(JsObject("name" -> JsString("John")))

Upvotes: 1

Carlos Vilchez
Carlos Vilchez

Reputation: 2804

If you need to make your reply an application/json, you should use something like:

respondWithMediaType(MediaTypes.`application/json`) {
     complete { ...
     } 
}

Upvotes: 1

Related Questions