Akka HTTP uses the spray-json library for JSON support. But this year I’ve been spending some time learning the json4s library so I wanted to leverage that time investment in the context of Akka HTTP.

Here’s a quick walkthru of how to use the json4s with Akka HTTP.

Dependencies

I am using Gradle, so here is the relevant code from build.gradle

def scalaVersion = "2.12.1"
def akkaVersion = "2.5.7"
def json4sVersion = "3.5.0"

dependencies {
    // scala
    compile "org.scala-lang:scala-library:$scalaVersion"
    compile "org.scala-lang:scala-reflect:$scalaVersion"

    // json4s
    compile "org.json4s:json4s-ext_2.12:$json4sVersion"
    compile "org.json4s:json4s-jackson_2.12:$json4sVersion"
    compile "org.json4s:json4s-native_2.12:$json4sVersion"

    // json4s-akka http bridge
    compile "de.heikoseeberger:akka-http-json4s_2.12:1.19.0-M3"

    // akka
    compile "com.typesafe.akka:akka-stream_2.12:$akkaVersion"
    compile "com.typesafe.akka:akka-actor_2.12:$akkaVersion"
    compile "com.typesafe.akka:akka-http_2.12:10.0.11"
}

To get akka http and json4s to play nicely together, I am going to leverage a open source library I found on Github: akka-http-json

The implementation will involve creating a custom Trait that extends that akka-http-json library and also scopes the necessary implicit values.

Here’s our sample web server file that handles a GET request and responds with JSON:

package com.lombardo.server

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.{Directives, Route}
import akka.stream.ActorMaterializer
import de.heikoseeberger.akkahttpjson4s.Json4sSupport
import org.json4s.JsonDSL._
import org.json4s.jackson.JsonMethods.render

import scala.concurrent.ExecutionContextExecutor
import scala.util.{Failure, Success}

// custom trait for Json support
trait JsonSupport extends Json4sSupport {
  implicit val serialization = org.json4s.native.Serialization
  implicit val json4sFormats = org.json4s.DefaultFormats
}

// the usual config code required for an Akka Http server, mixing in our Json trait too
class WebServer(implicit system: ActorSystem, materializer: ActorMaterializer,
                executionContext: ExecutionContextExecutor)
  extends Directives with JsonSupport {

  // set up a demo route using the #render method of json4s.jackson
  // this allows us to send native Scala code back as Json
  val getHome = get {
    complete(render("message" -> "welcome to the fun house"))
  }

  val restfulRoutes: Route = path("home") {
    getHome
  }

  val bindingFuture = Http().bindAndHandle(restfulRoutes, "0.0.0.0", 8080)

  bindingFuture.onComplete {
    case Success(binding) 
      println(s"Webserver is listening on localhost:8080")
    case Failure(e) 
      println(s"Binding failed with ${e.getMessage}")
      system.terminate()
  }
}

In mainclass:

package com.lombardo

import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import com.lombardo.server.WebServer

import scala.concurrent.ExecutionContextExecutor

object Main {
  def main(args: Array[String]) {
    println("Hello from Akka-Http starter pack!")
    implicit val system = ActorSystem("demo-system")
    implicit val materializer = ActorMaterializer()
    implicit val executionContext:ExecutionContextExecutor = system.dispatcher

    val webServer = new WebServer
  }
}
curl localhost:8080/home | jq

# {
#  "message": "welcome to the fun house"
# }

In the next post we will setup a POST endpoint and “unmarshall” some Json.