使用自定义ToEntityMarshaller

时间:2016-10-16 14:58:54

标签: akka-http

我为类型ToEntityMarshaller定义了自定义Organisation。请求localhost:8080/organisations时,它返回一个空的JSON数组。只有当我删除implicit def organisationMarshaller: ToEntityMarshaller[Organisation]时,它才会返回正确的流表示。

有人知道这里发生了什么吗?

import akka.NotUsed
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.common.{EntityStreamingSupport, JsonEntityStreamingSupport}
import akka.http.scaladsl.model.{HttpEntity, StatusCodes, _}
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller, ToResponseMarshaller}
import akka.http.scaladsl.model.TransferEncodings.gzip
import akka.http.scaladsl.model.headers.{HttpEncoding, HttpEncodings}
import akka.stream.scaladsl.{Flow, Source}
import akka.util.ByteString
import spray.json.DefaultJsonProtocol
import spray.json.DefaultJsonProtocol._

import scala.concurrent.Future
import scala.io.StdIn
import scala.util.Random

final case class Organisation(name: String, id: String)

trait Protocols extends DefaultJsonProtocol {

  import spray.json._

  implicit val organisationFormat = jsonFormat2(Organisation)

  val `vnd.example.api.v1+json` =
    MediaType.applicationWithFixedCharset("vnd.example.api.v1+json", HttpCharsets.`UTF-8`)

  // -- WORKS AFTER REMOVING THIS DECLARATION --
  implicit def organisationMarshaller: ToEntityMarshaller[Organisation] = Marshaller.oneOf(
    Marshaller.withFixedContentType(`vnd.example.api.v1+json`) { organisation =>
      HttpEntity(`vnd.example.api.v1+json`, organisation.toJson.compactPrint)
    })
}

object Server extends App with Protocols {
  implicit val system = ActorSystem("api")
  implicit val materializer = ActorMaterializer()
  implicit val executionContext = system.dispatcher

  implicit val jsonStreamingSupport: JsonEntityStreamingSupport = EntityStreamingSupport.json()
    .withParallelMarshalling(parallelism = 10, unordered = false)

  // (fake) async database query api
  def dummyOrganisation(id: String) = Organisation(s"Organisation $id", id.toString)

  def fetchOrganisation(id: String): Future[Option[Organisation]] = Future(Some(dummyOrganisation(id)))

  def fetchOrganisations(): Source[Organisation, NotUsed] = Source.fromIterator(() => Iterator.fill(10000) {
    val id = Random.nextInt()
    dummyOrganisation(id.toString)
  })

  val route =
    encodeResponse {
      pathPrefix("organisations") {
        get {
          val organisations = fetchOrganisations()
          complete(organisations)
        }
      }
    }


  val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)

  println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
  StdIn.readLine()
  bindingFuture.flatMap(_.unbind()).onComplete(_ => system.terminate())
}

0 个答案:

没有答案