使用spala中的spray编写一个简单的json REST服务器

jon*_*rry 21 json scala spray

我想使用spala支持以下路由实现一个简单的json REST服务器:

GET /foo => return a list of case class objects in json format
POST /bar => read a json into a case class object and perform some computation
Run Code Online (Sandbox Code Playgroud)

我的基本入门代码如下:

import spray.routing.SimpleRoutingApp
import spray.can.Http
import akka.actor.ActorSystem
import akka.actor.Props
import akka.io.IO
import scala.collection.JavaConversions
import com.fasterxml.jackson.databind.ObjectMapper

object SprayTest extends App with SimpleRoutingApp {
  implicit val system = ActorSystem("my-system")
  val mapper = new ObjectMapper

  case class Foo(a: String, b: Int)
  case class Bar(c: Long, d: String)

  startServer(interface = "localhost", port = 8080) {
    get {
      path("foo") {
        complete {
          val c = listOfFoo()
          mapper.writeValueAsString(c)
        }
      }
    } ~ post {
      path("bar") {
        val bar: Bar = ???
        complete {
          "???"
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我所知道的这个代码最重要的两个问题是:

  1. 我依赖于jackson,但是从搜索网络来看,似乎spray应该有一些内置的支持来序列化和反序列化简单的case对象或case对象列表.

  2. 我不确定从post请求获取内容的"最佳",最惯用和简洁的方法,并将其编组到json中,以便我可以对case类对象执行一些计算

有谁知道最好的方法?有没有办法使编组自动化,所以我可以执行类似的东西complete { caseObject }caseObject自动转换为json(反之亦然,定义POST方法)?

Gan*_*ead 20

绝对使用喷雾json.通常将数据模型分成自己的文件:

import spray.json._

case class Foo(a: String, b: Int)
case class Bar(c: Long, d: String)

object FooBarJsonProtocol extends DefaultJsonProtocol{
    implicit val fooFormat = jsonFormat2(Foo)
    implicit val barFormat = jsonFormat2(Bar)
}
Run Code Online (Sandbox Code Playgroud)

然后在路线上

    import FooBarJsonProtocol._
    ...
    get {
      path("foo") {
        complete {
          listOfFoo() //with the implicit in scope this will serialize as json
        }
      }
    } ~ post {
      path("bar") {
        entity(as[Bar]) { bar =>  //extract json Bar from post body
          complete(bar) //serialize bar to json (or whatever processing you want to do)
        }
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

  • 在`spray-json` 1.3.3中重要的是导入`import spray.httpx.SprayJsonSupport._` (4认同)

Ami*_*ico 7

我无法想象为什么这个问题被低估了 - 似乎具体而且表达得很好.

这有点难以找到,但Spray文档涵盖了Spray Routing/Advanced Topics下的案例类提取.在这里重复解释是没有意义的,但基本上你想as[Foo]用来将HTTP内容反序列化为对象.该entity指令可用于为请求主体执行此操作,如此喷涂路由DSL的较长示例所示. mapTo(在同一示例中使用)可能是您要为响应序列化对象的内容.

对于JSON,它可能最容易使用它们单独的Spray-JSON库,因为它可以直接插入到它们的类型类机制中,但我认为你可以通过一些努力结合你想要的任何东西.Spray-JSON可以使用一行胶水处理案例类.

顺便说一句,val bar: Bar = ???示例代码中的行将在定义路由时执行,而不是在请求进入时执行,正如您可能想要的那样.请阅读spray-routing文档中的了解DSL结构部分.