【问题标题】:How to unmarshall akka http request entity as string?如何将akka http请求实体解组为字符串?
【发布时间】:2015-08-30 21:34:05
【问题描述】:

我正在尝试将请求负载解组为字符串,但由于某种原因它失败了。我的代码:

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

例如,在这个SO thread 中,似乎默认情况下应该可以使用这个隐式。但也许这在 akka-http 中有所不同?

我尝试导入具有stringUnmarshallerakka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallers,但没有帮助。可能是因为这返回类型 FromEntityUnmarshaller[String] 而不是 FromRequestUnmarshaller[String]spray.httpx.unmarshalling.BasicUnmarshallers 中还有一个字符串解组器,但这也无济于事,akka.http.scaladsl.unmarshalling.PredefinedFromStringUnmarshallers

如何解组(和编组)成字符串?

(奖励:如何直接在 JsObject 中解组(播放 json)。但也只有字符串,因为我对为什么这不起作用并且它可能对其他情况有用)。

使用 1.0-RC3

谢谢。

【问题讨论】:

    标签: json scala akka-http


    【解决方案1】:

    只要你在范围内有正确的隐式,你的代码应该没问题。如果您在范围内有一个隐式FlowMaterializer,那么事情应该按预期工作,因为编译的代码显示:

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

    如果您想更进一步并解组到 JsObject,那么您只需要在范围内隐式 Unmarshaller 来处理该转换,如下所示:

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

    【讨论】:

    • 谢谢!我的问题是我在路由定义下面声明了 ActorFlowMaterializer 隐含......很难发现这是编组部分不编译的原因,对于像我这样的新手来说是不可能的......
    • 除此之外,我一定错过了在声明隐式或其他内容时顺序很重要,因为变量在范围内 - 就在路线下方。
    • 也感谢 json unmarshaller,我实际上使用的是字符串,而不是 byteString(这只是一个测试),但可以轻松调整它以使用字符串。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-09
    • 1970-01-01
    相关资源
    最近更新 更多