JSON Support

Akka HTTP’s marshalling and unmarshalling infrastructure makes it rather easy to seamlessly convert application-domain objects from and to JSON. Integration with spray-json is provided out of the box through the akka-http-spray-json module. Integration with other JSON libraries are supported by the community. See the list of current community extensions for Akka HTTP.

spray-json Support

The SprayJsonSupport trait provides a FromEntityUnmarshaller[T] and ToEntityMarshaller[T] for every type T that an implicit spray.json.RootJsonReader and/or spray.json.RootJsonWriter (respectively) is available for.

To enable automatic support for (un)marshalling from and to JSON with spray-json, add a library dependency onto:

sbt
libraryDependencies += "com.typesafe.akka" %% "akka-http-spray-json" % "10.0.15"
Gradle
dependencies {
  compile group: 'com.typesafe.akka', name: 'akka-http-spray-json_2.12', version: '10.0.15'
}
Maven
<dependency>
  <groupId>com.typesafe.akka</groupId>
  <artifactId>akka-http-spray-json_2.12</artifactId>
  <version>10.0.15</version>
</dependency>

Next, provide a RootJsonFormat[T] for your type and bring it into scope. Check out the spray-json documentation for more info on how to do this.

Finally, import the FromEntityUnmarshaller[T] and ToEntityMarshaller[T] implicits directly from SprayJsonSupport as shown in the example below or mix the akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport trait into your JSON support module.

Once you have done this (un)marshalling between JSON and your type T should work nicely and transparently.

import akka.http.scaladsl.server.Directives
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import spray.json._

// domain model
final case class Item(name: String, id: Long)
final case class Order(items: List[Item])

// collect your json format instances into a support trait:
trait JsonSupport extends SprayJsonSupport with DefaultJsonProtocol {
  implicit val itemFormat = jsonFormat2(Item)
  implicit val orderFormat = jsonFormat1(Order) // contains List[Item]
}

// use it wherever json (un)marshalling is needed
class MyJsonService extends Directives with JsonSupport {

  // format: OFF
  val route =
    get {
      pathSingleSlash {
        complete(Item("thing", 42)) // will render as JSON
      }
    } ~
    post {
      entity(as[Order]) { order => // will unmarshal JSON to Order
        val itemsCount = order.items.size
        val itemNames = order.items.map(_.name).mkString(", ")
        complete(s"Ordered $itemsCount items: $itemNames")
      }
    }
  // format: ON
}

Pretty printing

By default, spray-json marshals your types to compact printed JSON by implicit conversion using CompactPrinter, as defined in:

implicit def sprayJsonMarshallerConverter[T](writer: RootJsonWriter[T])(implicit printer: JsonPrinter = CompactPrinter): ToEntityMarshaller[T] =
  sprayJsonMarshaller[T](writer, printer)

Alternatively to marshal your types to pretty printed JSON, bring a PrettyPrinter in scope to perform implicit conversion.

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import spray.json._

// domain model
final case class PrettyPrintedItem(name: String, id: Long)

object PrettyJsonFormatSupport {
  import DefaultJsonProtocol._
  implicit val printer = PrettyPrinter
  implicit val prettyPrintedItemFormat = jsonFormat2(PrettyPrintedItem)
}

// use it wherever json (un)marshalling is needed
class MyJsonService extends Directives {
  import PrettyJsonFormatSupport._

  // format: OFF
  val route =
    get {
      pathSingleSlash {
        complete {
          PrettyPrintedItem("akka", 42) // will render as JSON
        }
      }
    }
  // format: ON
}

val service = new MyJsonService

// verify the pretty printed JSON
Get("/") ~> service.route ~> check {
  responseAs[String] shouldEqual
    """{""" + "\n" +
    """  "name": "akka",""" + "\n" +
    """  "id": 42""" + "\n" +
    """}"""
}

To learn more about how spray-json works please refer to its documentation.

The source code for this page can be found here.