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. Java Sftp上传下载文件

    需要使用jar包  jsch-0.1.50.jar sftp上传下载实现类 package com.bstek.transit.sftp; import java.io.File; import ja ...

  2. Jmeter运行结果分析

    1.聚合报告 以上就是我们所关心的结果 Label:页面或请求名称 Samples:运行的线程数(也可理解为请求数) Average:平均响应时间 Median:响应时间的中值 90% Line:90 ...

  3. spark、storm与Hadoop

    1. Storm是什么,怎么做,如何做的更好?Storm是一个开源的分布式实时计算系统,它可以简单.可靠地处理大量的数据流.Storm有很多应用场景,如实时分析.在线机器学习.持续计算.分布式RPC. ...

  4. border-radius:50%和100%究竟有什么区别

    之前写css圆形时总是直接设置border-radius为50%.后来看某css动画网站时发现作者都是用的100%.遂去了解了一下2者的差别. border-radius的值是百分比的话,就相当于盒子 ...

  5. vue2.0 网页标题更新实现思路

    一.注册全局指令 1.注册一个全局指令 Vue.directive('title', { inserted: function (el, binding) { document.title = el. ...

  6. sqoop使用的问题

    找不到表 17/05/02 18:15:47 ERROR tool.ImportTool: Imported Failed: There is no column found in the targe ...

  7. Linux入门之常用命令(13) date

    在linux shell编程中,经常用到日期的加减运算 以前都是自己通过expr函数计算,很麻烦 其实date命令本身提供了日期的加减运算 非常方便.例如:得到昨天的时间date +%Y%m%d -- ...

  8. hdu 5937 -- Equation(搜索)

    题目链接 problem description Little Ruins is a studious boy, recently he learned addition operation! He ...

  9. 分布式系统中生成全局ID的总结与思考

    世间万物,都有自己唯一的标识,比如人,每个人都有自己的指纹(白夜追凶给我科普的,同卵双胞胎DNA一样,但指纹不一样).又如中国人,每个中国人有自己的身份证.对于计算机,很多时候,也需要为每一份数据生成 ...

  10. bzoj2257 [Jsoi2009]瓶子和燃料 最大公约数

    [Jsoi2009]瓶子和燃料 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1449  Solved: 889[Submit][Status][Di ...