2015-10-07 4 views
1

У меня есть код, который выглядит так.Как сериализовать объекты с/на 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 и сделал их неявными, я использую классы case, чего мне здесь не хватает? Я новичок в скале и спрее, поэтому мне это непонятно.

ответ

2

Для вас класс, вы должны предоставить Маршаллера и 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:

0

Я думаю, вам просто нужно смешать spray.httpx.Json4sSupport в своем классе. Итак ...

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

Первоначально я предоставлял общий ответ для подхода к использованию спрей-джсона. Но после повторного чтения я понял, что отвечаю на неправильный вопрос. Я оставлю свой первоначальный ответ ниже, если кто-то окажется полезным.

Мой предпочтительный подход - создать черту, которая расширяет возможности Spray по умолчанию JsonProtocol и SprayJsonSupport. Внутри этого я создаю неявные ссылки на RootJsonFormats для всех классов case. Затем я просто смешиваю эту черту с классом или чертой, где мой маршрут определен.

Для меня это самый простой способ сохранить организованность и предоставить необходимые (un) функции маршалинга для моих маршрутов 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()) 
    } 
    } 
} 

Если у вас есть дополнительные классы, которые требуют (не) маршалингом, просто добавить еще один неявный RootJsonFormat для каждого из этих классов к вашему MyAppJsonProtocol черты.