2015-06-15 5 views
11

Ich versuche, Nutzlast als String abzumelden, aber aus irgendeinem Grund schlägt es fehl. Mein Code:Wie man Akka HTTP Request Entity als String unmarshall?

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 diesem SO thread zum Beispiel, es zu sein scheint, dass diese implizite standardmäßig verfügbar sein sollte. Aber vielleicht ist das bei akka-http anders?

Ich habe versucht, akka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallers zu importieren, die eine stringUnmarshaller hat, aber es hilft nicht. Vielleicht, weil dieser Typ FromEntityUnmarshaller[String] nicht FromRequestUnmarshaller[String] zurückgibt. Es gibt auch einen String-Unmarshaller in spray.httpx.unmarshalling.BasicUnmarshallers, aber das hilft auch nicht, weder akka.http.scaladsl.unmarshalling.PredefinedFromStringUnmarshallers

Wie kann ich marshall (und marshall) in eine Zeichenfolge?

(Bonus: Wie man direkt in einem JsObject abmarshall (play json). Aber auch nur String, da ich daran interessiert bin, warum das nicht funktioniert und es kann für andere Fälle nützlich sein).

Mit 1.0-RC3

Dank.

Antwort

15

Ihr Code sollte in Ordnung sein vorausgesetzt, Sie haben das Recht im Umfang. Wenn Sie eine implizite FlowMaterializer in Umfang haben, dann sollten Dinge wie dieser Code erwartet funktionieren, die zeigt kompiliert:

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

Wenn Sie wollten einen Schritt weiter, Dinge nehmen und entordnen zu einem JsObject dann brauchen Sie nur eine implizite Unmarshaller in Bereich, um diese Umwandlung zu behandeln, etwas wie folgt:

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

Danke! Mein Problem war, dass ich den ActorFlowMaterializer implizit unterhalb der Routen-Definition deklarierte ... es ist ziemlich schwer zu erkennen, dass dies der Grund dafür ist, dass der Marshalling-Teil nicht kompiliert wird, für einen Neuling wie mich einfach unmöglich ... – Ixx

+0

Außerdem muss ich haben verpasst, dass diese Reihenfolge wichtig ist, wenn sie Implikationen oder etwas anderes deklariert, weil die Variablen in Reichweite waren - gerade unterhalb der Routen. – Ixx

+0

Danke auch für den jsons-unmarshaller, ich benutze tatsächlich string, nicht byteString (das war nur ein Test), aber könnte es leicht anpassen, mit string zu arbeiten. – Ixx