分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 技术分享

Akka(34): Http:Unmarshalling,from Json

发布时间:2023-09-06 01:21责任编辑:彭小芳关键词:暂无标签

  Unmarshalling是Akka-http内把网上可传输格式的数据转变成程序高级结构话数据的过程,比如把Json数据转换成某个自定义类型的实例。按具体流程来说就是先把Json转换成可传输格式数据如:MessageEntity,HttpRequest,HttpReponse等,然后再转换成程序高级结构数据如classXX实例。Unmarshalling对一个A类实例到B类实例的转换是通过Unmarshaller[A,B]来实现的:

trait Unmarshaller[-A, B] extends akka.http.javadsl.unmarshalling.Unmarshaller[A, B] {...}object Unmarshaller ?extends GenericUnmarshallers ?with PredefinedFromEntityUnmarshallers ?with PredefinedFromStringUnmarshallers { ?// format: OFF ?//#unmarshaller-creation ?/** ??* Creates an `Unmarshaller` from the given function. ??*/ ?def apply[A, B](f: ExecutionContext ? A ? Future[B]): Unmarshaller[A, B] = ???withMaterializer(ec => _ => f(ec))...}

从Unmarshaller的构建函数apply可以估计它的作用应该与函数A=>Future[B]很相似。A代表网上可传输类型如MessageEntity、HttpRequest,B代表某种程序高级数据类型。因为A到B的转换是non-blocking的,所以可以立即返回Future类型结果。Akka-http按被转换对象类型分类命名了下面这些类型别名:

type FromEntityUnmarshaller[T] = Unmarshaller[HttpEntity, T]type FromMessageUnmarshaller[T] = Unmarshaller[HttpMessage, T]type FromResponseUnmarshaller[T] = Unmarshaller[HttpResponse, T]type FromRequestUnmarshaller[T] = Unmarshaller[HttpRequest, T]type FromByteStringUnmarshaller[T] = Unmarshaller[ByteString, T]type FromStringUnmarshaller[T] = Unmarshaller[String, T]type FromStrictFormFieldUnmarshaller[T] = Unmarshaller[StrictForm.Field, T]

Akka-http对以下类型提供了自动的Unmarshalling转换: 

PredefinedFromStringUnmarshallersByteShortIntLongFloatDoubleBooleanPredefinedFromEntityUnmarshallersArray[Byte]ByteStringArray[Char]Stringakka.http.scaladsl.model.FormDataGenericUnmarshallersUnmarshaller[T, T] (identity unmarshaller)Unmarshaller[Option[A], B], if an Unmarshaller[A, B] is availableUnmarshaller[A, Option[B]], if an Unmarshaller[A, B] is available

也就是说Akka-http提供了这些U类型的Unmarshaller[U,B]隐式实例。Akka-http也提供了工具类型Unmarshal:

object Unmarshal { ?def apply[T](value: T): Unmarshal[T] = new Unmarshal(value)}class Unmarshal[A](val value: A) { ?/** ??* Unmarshals the value to the given Type using the in-scope Unmarshaller. ??* ??* Uses the default materializer [[ExecutionContext]] if no implicit execution context is provided. ??* If you expect the marshalling to be heavy, it is suggested to provide a specialized context for those operations. ??*/ ?def to[B](implicit um: Unmarshaller[A, B], ec: ExecutionContext = null, mat: Materializer): Future[B] = { ???val context: ExecutionContext = if (ec == null) mat.executionContext else ec ???um(value)(context, mat) ?}}

我们可以通过Unmarshal.to[B]把Unmarshal[A]转换成Future[B]。注意:这一步只包括了从网上可传输类型到程序类型转换这一过程,不包括具体实现时的Json转换。下面是一些Unmarshal的用例:

import akka.actor._import akka.stream._import akka.http.scaladsl.unmarshalling.Unmarshalimport akka.http.scaladsl.model._import akka.http.scaladsl.server.Directives._object Unmarshalling { ?implicit val httpSys = ActorSystem("httpSystem") ?implicit val httpMat = ActorMaterializer() ?implicit val httpEC = httpSys.dispatcher ?val futInt = Unmarshal(43).to[Int] ?val futBoolean = Unmarshal("0").to[Boolean] ?val futString = Unmarshal(HttpEntity("Hello")).to[String] ?val futHello = Unmarshal(HttpRequest(method = HttpMethods.GET, entity = HttpEntity("hello")))}

以上都是已知类型之间转换,可能没什么实际用途,不像marshalling:中间层Marshalling有实际转换的需要。Unmarshalling可以直接进行Json到自定义类型之间的转换,如:

 val route = (path("User") & post) { entity(as[User]){ user => ???complete(Future(s"inserting user: $user")) ?}} ~ ???(path("Item"/IntNumber) & put) { id => entity(as[Item]){ item => ?????complete(Future(s"update item $id: $item")) ???}}

以上是通过Directive as[???]实现的:

 /** ??* Returns the in-scope [[FromRequestUnmarshaller]] for the given type. ??* ??* @group marshalling ??*/ ?def as[T](implicit um: FromRequestUnmarshaller[T]) = um

这需要把FromRequestUmarshaller[T]放在可视域内,FromRequestUmarshaller[T]实际是Unmarshaller[T,B]的别名: 

type FromRequestUnmarshaller[T] = Unmarshaller[HttpRequest, T]

在上篇讨论我们介绍了Akka-http的Marshalling是type-class模式的。其中关键可以参考上篇讨论。现在我们需要这些Unmarshaller的隐式实例:

trait Formats extends SprayJsonSupport with DefaultJsonProtocolobject Converters extends Formats { ?case class User(id: Int, name: String) ?case class Item(id: Int, name: String, price: Double) ?implicit val itemFormat = jsonFormat3(Item.apply) ?implicit val userFormat = jsonFormat2(User.apply)}object Unmarshalling { ?import Converters._...

如果使用Json4s的实现方式,我们需要如下提供这些隐式实例:

trait JsonCodec extends Json4sSupport { ?import org.json4s.DefaultFormats ?import org.json4s.ext.JodaTimeSerializers ?implicit val serilizer = jackson.Serialization ?implicit val formats = DefaultFormats ++ JodaTimeSerializers.all}object JsConverters extends JsonCodec

Json4s的具体用例如下:

 ?import scala.collection.mutable._ ?case class User(id: Int, name: String) ?class Item(id: Int, name: String, price: Double) ?object AnyPic { ???val area = 10 ???val title = "a picture" ???val data = ArrayBuffer[Byte](1,2,3) ?} ?val route = (path("User") & post) { entity(as[User]){ user => ???complete(Future(s"inserting user: $user")) ?}} ~ ???(path("Item"/IntNumber) & put) { id => entity(as[Item]){ item => ?????complete(Future(s"update item $id: $item")) ???}} ~ ???(path("Picture") & put) { entity(as[AnyPic.type]){ pic => ?????complete(Future(s"insert picture: $pic")) ???}}

从功能上和表达灵活性来讲,Json4s的实现方式要占优。

下面就是本次讨论的示范源代码:

Unmarshalling

import akka.actor._import akka.stream._import akka.http.scaladsl.unmarshalling.Unmarshalimport akka.http.scaladsl.model._import akka.http.scaladsl.server.Directives._import scala.concurrent._import akka.http.scaladsl.marshallers.sprayjson._import spray.json._trait Formats extends SprayJsonSupport with DefaultJsonProtocolobject Converters extends Formats { ?case class User(id: Int, name: String) ?case class Item(id: Int, name: String, price: Double) ?implicit val itemFormat = jsonFormat3(Item.apply) ?implicit val userFormat = jsonFormat2(User.apply)}object Unmarshalling { ?import Converters._ ?implicit val httpSys = ActorSystem("httpSystem") ?implicit val httpMat = ActorMaterializer() ?implicit val httpEC = httpSys.dispatcher ?val futInt = Unmarshal(43).to[Int] ?val futBoolean = Unmarshal("0").to[Boolean] ?val futString = Unmarshal(HttpEntity("Hello")).to[String] ?val futHello = Unmarshal(HttpRequest(method = HttpMethods.GET, entity = HttpEntity("hello"))) ?val route = (path("User") & post) { entity(as[User]){ user => ???complete(Future(s"inserting user: $user")) ?}} ~ ???(path("Item"/IntNumber) & put) { id => entity(as[Item]){ item => ?????complete(Future(s"update item $id: $item")) ???}}}

Json4sUnmarshalling

import akka.actor._import akka.stream._import akka.http.scaladsl.server.Directives._import de.heikoseeberger.akkahttpjson4s.Json4sSupportimport org.json4s.jacksonimport scala.concurrent._trait JsonCodec extends Json4sSupport { ?import org.json4s.DefaultFormats ?import org.json4s.ext.JodaTimeSerializers ?implicit val serilizer = jackson.Serialization ?implicit val formats = DefaultFormats ++ JodaTimeSerializers.all}object JsConverters extends JsonCodecobject Json4sUnmarshalling { ?import JsConverters._ ?implicit val httpSys = ActorSystem("httpSystem") ?implicit val httpMat = ActorMaterializer() ?implicit val httpEC = httpSys.dispatcher ?import scala.collection.mutable._ ?case class User(id: Int, name: String) ?class Item(id: Int, name: String, price: Double) ?object AnyPic { ???val area = 10 ???val title = "a picture" ???val data = ArrayBuffer[Byte](1,2,3) ?} ?val route = (path("User") & post) { entity(as[User]){ user => ???complete(Future(s"inserting user: $user")) ?}} ~ ???(path("Item"/IntNumber) & put) { id => entity(as[Item]){ item => ?????complete(Future(s"update item $id: $item")) ???}} ~ ???(path("Picture") & put) { entity(as[AnyPic.type]){ pic => ?????complete(Future(s"insert picture: $pic")) ???}}}

Akka(34): Http:Unmarshalling,from Json

原文地址:http://www.cnblogs.com/tiger-xc/p/7763466.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved