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转换:

PredefinedFromStringUnmarshallers
Byte
Short
Int
Long
Float
Double
Boolean
PredefinedFromEntityUnmarshallers
Array[Byte]
ByteString
Array[Char]
String
akka.http.scaladsl.model.FormData
GenericUnmarshallers
Unmarshaller[T, T] (identity unmarshaller)
Unmarshaller[Option[A], B], if an Unmarshaller[A, B] is available
Unmarshaller[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.Unmarshal
import 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().to[Int]
val futBoolean = Unmarshal("").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 DefaultJsonProtocol
object 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 =
val title = "a picture"
val data = ArrayBuffer[Byte](,,)
} 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.Unmarshal
import 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 DefaultJsonProtocol
object 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().to[Int]
val futBoolean = Unmarshal("").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.Json4sSupport
import org.json4s.jackson
import 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 JsonCodec object 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 =
val title = "a picture"
val data = ArrayBuffer[Byte](,,)
} 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的更多相关文章

  1. Scalaz(34)- Free :算法-Interpretation

    我们说过自由数据结构(free structures)是表达数据类型的最简单结构.List[A]是个数据结构,它是生成A类型Monoid的最简单结构,因为我们可以用List的状态cons和Nil来分别 ...

  2. Java知多少(34)final关键字:阻止继承和多态

    在 Java 中,声明类.变量和方法时,可使用关键字 final 来修饰.final 所修饰的数据具有“终态”的特征,表示“最终的”意思.具体规定如下: final 修饰的类不能被继承. final ...

  3. 曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean definition的?

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码系列开讲了(1)-- Bean Definition到底是什么,附spring思维导图分享 工程代码地址 思维导图地址 工程结构图: 大 ...

  4. html5实现饼图和线图-我们到底能走多远系列(34)

    我们到底能走多远系列(34) 扯淡: 送给各位一段话:     人生是一个不断做加法的过程     从赤条条无牵无挂的来     到学会荣辱羞耻 礼仪规范     再到赚取世间的名声 财富 地位    ...

  5. 曹工说Spring Boot源码(7)-- Spring解析xml文件,到底从中得到了什么(上)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  6. 曹工说Spring Boot源码(8)-- Spring解析xml文件,到底从中得到了什么(util命名空间)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  7. 曹工说Spring Boot源码(9)-- Spring解析xml文件,到底从中得到了什么(context命名空间上)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  8. # 曹工说Spring Boot源码(10)-- Spring解析xml文件,到底从中得到了什么(context:annotation-config 解析)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  9. 曹工说Spring Boot源码(12)-- Spring解析xml文件,到底从中得到了什么(context:component-scan完整解析)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

随机推荐

  1. 随便讲讲我对于svn和git的想法

    1.SVN是集中式版本管理工具,而Git是分布式版本管理工具,这是核心区别. 二者都有集中的库,只是git偏向于分布式,用户可以再自己电脑上克隆一份自己的库,即使在断网的情况下也能够查看版本,创建分支 ...

  2. java web项目修改favicon.ico图标的方式

    1.修改整个项目的tomcat图标 找到tomcat的根目录(tomcat-webapps-ROOT目录),然后将修改的favicon.ico图标覆盖掉本地的图标,然后再重启项目,刷新,清除浏览器缓存 ...

  3. Mybatis逆向生成Mapper文件

    本文参考博客 http://blog.csdn.net/for_my_life/article/details/51228098 1. 在resources根目录下添加generator.proper ...

  4. myeclipse快捷键(转载)

    非常感谢分享这篇文章的大虾..但是我忘了几下您的blog地址,因此无法注明原文地址...见谅哈 存盘 Ctrl+s(肯定知道) 注释代码 Ctrl+/ 取消注释 Ctrl+\(Eclipse3已经都合 ...

  5. C++运算符优先级 案例1

    问: ... short nReaderCount=10              ++pLock->nReaderCount==? ...++和->同为1级优先级,我想很多也有很多新手弄 ...

  6. 分享基于分布式Http长连接框架

    第一次在博客园写文章,长期以来只是潜水中.本着不只索取,而要奉献的精神,随笔文章之. 现贡献一套长连接的框架.如下特性: 1:发布者可异步发送消息,消息如果发送失败,可重试发送,重试次数基于配置,消息 ...

  7. python对列表的联想

    python的列表与字典,已经接触无数次了.但是很多用法都记不住,个人觉得归根原因都是只是学了知识点而少用,也少思考.在此试图用宫殿记忆法对它们的用法做个简单的梳理. 首先,说说列表的删除,删除有三种 ...

  8. ios实现无限后台任务

    需求 我们的app是使用心跳机制来保持用户的登陆状态,这样才能收到服务器发来的消息和命令,但是当app进入后台以后大约3分钟或者10分钟之后app就会被系统挂起,用户就会超时下线,这样就必须保持app ...

  9. Jquery qTip2实现多种提示效果,支持ajax,以及多种样式

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. 【特效】jquery选项卡插件,页面多个选项卡统一调用

    把选项卡整合了一下,写成个插件,这样可以整个站,或整个页面有多个选项卡时,统一调用.代码的具体注意事项已经写进注释了.用于js获取元素的class名称必须有,选项卡本身的样式,另再取一个名字来设置(本 ...