如何为 spray+akka actor 设置隐式 json 转换

How to setup implicit json convertion for spray+akka actor

我是 Java 开发人员,对 Scala 还很陌生。

我正在实施一些使用 spray 和 akka 的休息 API API 应该公开某种用户 CRUD。我只会在这个问题中使用创建用户...

trait DefaultJsonFormats extends DefaultJsonProtocol with SprayJsonSupport with MetaMarshallers {}

class RegistrationService(registration: ActorRef)
   (implicit executionContext: ExecutionContext) 
                      extends Directives with DefaultJsonFormats {
implicit val timeout = Timeout(2.seconds)
implicit val userFormat = jsonFormat3(User)
implicit val registerFormat = jsonFormat1(Register)
implicit val registeredFormat = jsonFormat1(Registered)

  val route =
    path("register") {
      post {  handleWith { ru: Register => (registration ? ru).mapTo[Registered] } }
}

//------演员

object RegistrationActor {
  case class User(id:String, name:String)
  case class Register(user: User)
  case class Registered(status: String)
  case object NotRegistered
}

class RegistrationActor(implDef: String) extends Actor {
 def receive: Receive = {
    case Register(user)=>
        val status=// create user real code with return status
        sender ! new Registered(status)
 } }

在这种方法中,json 序列化和反序列化非常烦人。对于我需要处理的每个对象 API 我必须定义适当的格式

implicit val userFormat = jsonFormat3(User)
implicit val registerFormat = jsonFormat1(Register)
implicit val registeredFormat = jsonFormat1(Registered) 

我想避免这样的定义并使用一些通用的 json 转换器和 return 一个 pojo 对象,这样转换将在后台进行

问题是如何更改此代码以默认使用 Gson/Jackson/Spray 默认转换器并避免定义隐式... json格式?

For every object I need to deal with API I must define the appropriate format

通常在“JsonProtocol”class 中执行一次并在需要的地方导入,而不是每次都定义新格式:

import MyJsonProtocol._

val route =
  path("register") {
    post {  handleWith { ru: Register => (registration ? ru).mapTo[Registered] } }

how can I change this code to use by default Gson/Jackson/Spray default converter and avoid definition of the implicit ... jsonFormats?

您需要声明一个从 RegisteredHttpResponse 的隐式编组器(或像 String 这样的中间值),它由 Jackson 而不是 spray-json 支持,然后导入该编组器而不是 SprayJsonSupport.

查看 the implementation of SprayJsonSupport 了解如何执行此操作。如果您对隐式转换感到满意,这非常简单。

您还可以在 Spray 的 Json4sSupport 中看到这是如何完成的——该特性为所有类型 T 实现了 Marshaller[T, String]。然后,在运行时,Json4s 库将尝试将该对象序列化为 JSON.

In this approach the json serialization and desiarelization is pretty annoying

与杰克逊的方法相比,spray-json的方法有两个主要优点:

  • 没有反射,所以运行时更快
  • 这不是 JSON 格式的运行时决定,因此在编译时会发现任何问题