Skip to content

Instantly share code, notes, and snippets.

@davidmweber
Created March 30, 2014 08:48
Show Gist options
  • Save davidmweber/9869773 to your computer and use it in GitHub Desktop.
Save davidmweber/9869773 to your computer and use it in GitHub Desktop.
Route based marshalling example
package za.co.monadic.kumquat
import spray.testkit.ScalatestRouteTest
import org.scalatest.{FunSpec, Matchers}
import spray.json.DefaultJsonProtocol
import spray.routing.Directives._
import spray.httpx.marshalling.Marshaller
import spray.http.MediaTypes._
import spray.http.HttpEntity
// Data types that we trade in
case class Customer(name: String, no: Int)
case class Part( number: Int, name: String, length: Double)
// Marshallers for application/json (Spray's json)
object JsonMarshallers extends DefaultJsonProtocol {
implicit val customerM = jsonFormat2(Customer)
implicit val partM = jsonFormat3(Part)
}
// Custom marshalling for our text/plain
object TextMarshal {
implicit val customerM = Marshaller.of[Customer](`text/plain`) {
(value, content, ctx) => ctx.marshalTo(HttpEntity(content, value.toString))
}
implicit val partM = Marshaller.of[Part](`text/plain`) {
(value, content, ctx) => ctx.marshalTo(HttpEntity(content, value.toString))
}
}
// Map implicit
trait JsonApi {
import spray.httpx.SprayJsonSupport._
implicit val cm = sprayJsonMarshallerConverter(JsonMarshallers.customerM)
implicit val pm = sprayJsonMarshallerConverter(JsonMarshallers.partM)
}
trait TextApi {
implicit val cm = TextMarshal.customerM
implicit val pm = TextMarshal.partM
}
// Build marshal format independent routing
sealed trait Routes {
implicit val cm: Marshaller[Customer]
implicit val pm: Marshaller[Part]
val customer = path("customer" / IntNumber ){ id => complete(Customer("Frankie",id)) }
val part = path("part" / IntNumber ){ partNo => complete(Part(partNo,"Power flubber", 1.33)) }
val route = pathPrefix("v1_0" ) {
get {
part ~ customer
}
}
}
// Json mashalled route
object JsonRoutes extends Routes with JsonApi {
val topRoute = pathPrefix("api" / "json" ) { route }
}
// Text marshalled route
object TextRoutes extends Routes with TextApi {
val topRoute = pathPrefix("api" / "txt" ) { route }
}
/**
* Test case for the configuration above
*/
class RouteTest extends FunSpec with ScalatestRouteTest with Matchers{
import spray.json._
import JsonMarshallers._
describe("Our routes should") {
it("gets our customers as text") {
Get("/api/txt/v1_0/customer/233") ~> TextRoutes.topRoute ~> check {
responseAs[String] should equal(Customer("Frankie", 233).toString)
}
}
it("gets part details as text") {
Get("/api/txt/v1_0/part/233") ~> TextRoutes.topRoute ~> check {
responseAs[String] should equal(Part(233, "Power flubber", 1.33).toString)
}
}
it("gets our customers as JSON") {
Get("/api/json/v1_0/customer/233") ~> JsonRoutes.topRoute ~> check {
responseAs[String] should equal(Customer("Frankie", 233).toJson.prettyPrint)
}
}
it("gets our part details as JSON") {
Get("/api/json/v1_0/part/23") ~> JsonRoutes.topRoute ~> check {
responseAs[String] should equal(Part(23, "Power flubber", 1.33).toJson.prettyPrint)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment