2015-10-07 1 views
1

J'ai un code qui ressemble à ça.Comment sérialiser des objets de/vers json en spray avec defaultFormats?

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 
    } 
    } 
} 

Il me donne des erreurs comme ça

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

Mais dans ce tutorial un code similaire semble fonctionner. J'ai surchargé json4sFormats et je les ai implicites, j'utilise des classes de cas, qu'est-ce qui me manque ici? Je suis nouveau pour scala et spray, donc ce n'est pas clair pour moi.

Répondre

2

Pour votre classe, vous devez fournir Marshaller et Unmarshaller. De pulvérisation JSON Tutoriel:

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

et vous jeter à CursoredResponse Json

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

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

Voici le reference:

0

Je pense que vous avez juste besoin de mélanger spray.httpx.Json4sSupport dans votre classe. Donc ...

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

J'ai initialement fourni une réponse générique pour une approche d'utilisation de spray-json. Mais après avoir relu, j'ai réalisé que je répondais à la mauvaise question. Je vais laisser ma réponse originale ci-dessous au cas où quelqu'un trouverait cela utile.

Mon approche préférée consiste à créer un trait qui étend le DefaultJsonProtocol et SprayJsonSupport de Spray. À l'intérieur de cela, je crée des références implicites à RootJsonFormats pour toutes mes classes de cas. Ensuite, je viens de mélanger ce trait dans la classe ou le trait où mon itinéraire est défini. Pour moi, c'est le moyen le plus simple de garder les choses organisées et de fournir la fonctionnalité (un) marshaling nécessaire à mes routes de pulvérisation, ainsi que d'autres composants où j'utilise Spray client pour intégrer les fournisseurs de services HTTP qui produisent et consomme JSON.

Dites que vous avez un point de terminaison qui retourne un FooBar. Voici la classe de cas, nous voulons maréchal JSON:

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

Nous définissons un trait qui contient le RootJsonFormat pour nos classes personnalisées - dans ce cas un FooBar - qui sera en mesure de lire et d'écrire JSON

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

trait MyAppJsonProtocol extends DefaultJsonProtocol with SprayJsonSupport { 

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

Puis mélangez MyAppJsonProtocol dans la route.

trait FooBarRoute extends HttpService with MyAppJsonProtocol { 

    implicit def executionContext = actorRefFactory.dispatcher 

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

Si vous avez des classes supplémentaires qui nécessitent (un) marshaling, il suffit d'ajouter une autre RootJsonFormat implicite pour chacune de ces classes à votre trait MyAppJsonProtocol.