2015-06-15 15 views
11

Sto provando a scaricare il payload della richiesta di memoria come stringa, ma per qualche motivo non funziona. Il mio codice:Come rimuovere unmarshall akka http request entity come stringa?

path("mypath") { 

    post { 
    decodeRequest { 
     entity(as[String]) {jsonStr => //could not find implicit value for...FromRequestUnmarshaller[String] 
     complete { 
      val json: JsObject = Json.parse(jsonStr).as[JsObject] 
      val jsObjectFuture: Future[JsObject] = MyDatabase.addListItem(json) 
      jsObjectFuture.map(_.as[String]) 
     } 
     }   
    } 
    } 
} 

In questo SO thread per esempio sembra essere che questa implicita dovrebbe essere disponibile per impostazione predefinita. Ma forse questo è diverso in akka-http?

Ho provato a importare akka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallers che ha un stringUnmarshaller ma non aiuta. Forse perché restituisce il tipo FromEntityUnmarshaller[String] non FromRequestUnmarshaller[String]. C'è anche una stringa unmarshaller in spray.httpx.unmarshalling.BasicUnmarshallers ma anche questo non aiuta, né akka.http.scaladsl.unmarshalling.PredefinedFromStringUnmarshallers

Come posso unmarshall (e marshall) in una stringa?

(Bonus: come eseguire l'unmarshall direttamente in un JsObject (json), ma anche solo string perché sono interessato al motivo per cui non funziona e potrebbe essere utile per altri casi).

Utilizzando 1.0-RC3

Grazie.

risposta

15

Il codice deve essere a condizione che si disponga delle implicazioni corrette nell'ambito. Se si dispone di un implicito FlowMaterializer portata poi le cose dovrebbero funzionare nel modo previsto da questo codice che compila spettacoli:

import akka.http.scaladsl.server.Route 
import akka.actor.ActorSystem 
import akka.stream.ActorFlowMaterializer 
import akka.http.scaladsl.model.StatusCodes._ 
import akka.http.scaladsl.server.Directives._ 
import akka.stream.FlowMaterializer 

implicit val system = ActorSystem("test") 
implicit val mater = ActorFlowMaterializer() 

val routes:Route = { 
    post{ 
    decodeRequest{ 
     entity(as[String]){ str => 
     complete(OK, str) 
     } 
    } 
    }  
} 

Se si voleva prendere le cose un passo avanti e unmarshall ad un JsObject Poi basta un implicito Unmarshaller in portata per gestire tale conversione, qualcosa del genere:

implicit val system = ActorSystem("test") 
implicit val mater = ActorFlowMaterializer() 

import akka.http.scaladsl.unmarshalling.Unmarshaller 
import akka.http.scaladsl.model.HttpEntity 

implicit val um:Unmarshaller[HttpEntity, JsObject] = { 
    Unmarshaller.byteStringUnmarshaller.mapWithCharset { (data, charset) => 
    Json.parse(data.toArray).as[JsObject] 
    }  
} 

val routes:Route = { 
    post{ 
    decodeRequest{ 
     entity(as[String]){ str => 
     complete(OK, str) 
     } 
    } 
    } ~ 
    (post & path("/foo/baz") & entity(as[JsObject])){ baz => 
    complete(OK, baz.toString) 
    }  
} 
+0

Grazie! Il mio problema era che ho dichiarato che l'ActorFlowMaterializer era implicito sotto la definizione dei percorsi ... è abbastanza difficile notare che questo è il motivo per cui la parte di marshalling non si sta compilando, per un principiante come me semplicemente impossibile ... – Ixx

+0

Oltre a questo devo avere ha perso che l'ordine è importante quando si dichiarano impliciti, o qualcos'altro, perché le variabili erano nello scope - appena sotto le rotte. – Ixx

+0

Grazie anche a json unmarshaller, in realtà sto usando string, non byteString (questo era solo un test), ma potevo regolarlo facilmente per lavorare con la stringa. – Ixx

Problemi correlati