如何使用defaultFormats将对象从/到json序列化?

时间:2015-10-07 15:07:46

标签: json scala spray spray-json

我有一个看起来像这样的代码。

import akka.actor.{Props, ActorRef, Actor}
import akka.util.Timeout
import org.json4s.DefaultFormats
import spray.routing.HttpService
import spray.httpx.Json4sSupport
import scala.concurrent.Await
import scala.concurrent.duration._
import akka.pattern.ask

/**
 * Created by mihaildoronin on 06.10.15.
 */
class ProcessesService() extends Actor with HttpService {


  def actorRefFactory = context
  def receive = runRoute(route)

  val systemActor = context.actorOf(Props[SystemActor])
  implicit val json4sFormats = DefaultFormats
  implicit val timeout = Timeout(5 seconds)

  val route = path("processes") {
    get {
      parameters('fromId.as[Int], 'count.as[Int]).as(GetProcessesCommand) { command =>
        complete {
          val response = Await.result(systemActor ? command, timeout.duration).asInstanceOf[CursoredResponse]
          response
        }
      }

    } ~
    post {
      entity(as[RegisterProcessCommand]) { command =>
        complete {
          val result = Await.result(systemActor ? command, timeout.duration).asInstanceOf[Long]
        }
      }
    }
  } ~
  pathPrefix("processes" / IntNumber) { id =>
      complete {
      val process = Await.result(systemActor ? GetProcessCommand(id), timeout.duration).asInstanceOf[Process]
      process
    }
  }
}

它给了我这样的错误

Error:(28, 11) type mismatch;
 found   : CursoredResponse
 required: spray.httpx.marshalling.ToResponseMarshallable
          response
          ^

但在这个tutorial中,类似的代码似乎有效。我已经覆盖了json4sFormats并使它们隐含,我使用了案例类,我在这里缺少什么? 我是scala和spray的新手,所以我不清楚。

2 个答案:

答案 0 :(得分:2)

对于你的课程,你应该提供Marshaller和Unmarshaller。来自Spray Json教程:

import spray.json.DefaultJsonProtocol
import spray.httpx.unmarshalling._
import spray.httpx.marshalling._

并将你的CursoredResponse投给Json

import MyJsonProtocol._
import spray.httpx.SprayJsonSupport._
import spray.util._

object CursoredResponseProtocol extends DefaultJsonProtocol {
  implicit val CursoredResponseFormat = jsonFormat3(CursoredResponse)
}

这里是reference

答案 1 :(得分:0)

我认为你只需要将spray.httpx.Json4sSupport混合到你的类中。所以......

class ProcessesService() extends Actor with HttpService with Json4sSupport {
...
}

我最初提供了一个使用spray-json方法的通用答案。但重新阅读后,我意识到我正在回答错误的问题。我会在下面留下原来的答案,万一有人碰巧发现它有用。

我首选的方法是创建一个扩展Spray的DefaultJsonProtocol和SprayJsonSupport的特征。在其中,我为所有案例类创建对RootJsonFormats的隐式引用。然后我只是将该特征混合到我的路线定义的类或特征中。

对我来说,这是保持组织有序的最简单方法,并为我的Spray路由以及我使用Spray客户端与基于HTTP的服务提供商集成的其他组件提供所需的(联合)编组功能生成和使用JSON。

假设您有一个返回FooBar的端点。这是我们要编组给JSON的案例类:

case class FooBar(withNuts: Boolean = true, kingSize: Boolean = false)

我们定义一个特性,它包含我们自定义类的RootJsonFormat - 在本例中是一个FooBar - 它将能够读写JSON

import spray.json.{RootJsonFormat, DefaultJsonProtocol}
import spray.httpx.SprayJsonSupport

trait MyAppJsonProtocol extends DefaultJsonProtocol with SprayJsonSupport {

  implicit val FooBarFormat: RootJsonFormat[FooBar] = jsonFormat2(FooBar)
}

然后将MyAppJsonProtocol混合到路线中。

trait FooBarRoute extends HttpService with MyAppJsonProtocol {

  implicit def executionContext = actorRefFactory.dispatcher

  val fooRoute = {
    (get & path("foobar")) {
      complete(FooBar())
    }
  }
}

如果你有其他需要(un)封送的类,只需为MyAppJsonProtocol特性中的每个类添加另一个隐式RootJsonFormat。