Akka(34): Http:Unmarshalling,from Json
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的更多相关文章
- Scalaz(34)- Free :算法-Interpretation
我们说过自由数据结构(free structures)是表达数据类型的最简单结构.List[A]是个数据结构,它是生成A类型Monoid的最简单结构,因为我们可以用List的状态cons和Nil来分别 ...
- Java知多少(34)final关键字:阻止继承和多态
在 Java 中,声明类.变量和方法时,可使用关键字 final 来修饰.final 所修饰的数据具有“终态”的特征,表示“最终的”意思.具体规定如下: final 修饰的类不能被继承. final ...
- 曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean definition的?
写在前面的话 相关背景及资源: 曹工说Spring Boot源码系列开讲了(1)-- Bean Definition到底是什么,附spring思维导图分享 工程代码地址 思维导图地址 工程结构图: 大 ...
- html5实现饼图和线图-我们到底能走多远系列(34)
我们到底能走多远系列(34) 扯淡: 送给各位一段话: 人生是一个不断做加法的过程 从赤条条无牵无挂的来 到学会荣辱羞耻 礼仪规范 再到赚取世间的名声 财富 地位 ...
- 曹工说Spring Boot源码(7)-- Spring解析xml文件,到底从中得到了什么(上)
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- 曹工说Spring Boot源码(8)-- Spring解析xml文件,到底从中得到了什么(util命名空间)
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- 曹工说Spring Boot源码(9)-- Spring解析xml文件,到底从中得到了什么(context命名空间上)
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- # 曹工说Spring Boot源码(10)-- Spring解析xml文件,到底从中得到了什么(context:annotation-config 解析)
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- 曹工说Spring Boot源码(12)-- Spring解析xml文件,到底从中得到了什么(context:component-scan完整解析)
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
随机推荐
- Java Sftp上传下载文件
需要使用jar包 jsch-0.1.50.jar sftp上传下载实现类 package com.bstek.transit.sftp; import java.io.File; import ja ...
- Jmeter运行结果分析
1.聚合报告 以上就是我们所关心的结果 Label:页面或请求名称 Samples:运行的线程数(也可理解为请求数) Average:平均响应时间 Median:响应时间的中值 90% Line:90 ...
- spark、storm与Hadoop
1. Storm是什么,怎么做,如何做的更好?Storm是一个开源的分布式实时计算系统,它可以简单.可靠地处理大量的数据流.Storm有很多应用场景,如实时分析.在线机器学习.持续计算.分布式RPC. ...
- border-radius:50%和100%究竟有什么区别
之前写css圆形时总是直接设置border-radius为50%.后来看某css动画网站时发现作者都是用的100%.遂去了解了一下2者的差别. border-radius的值是百分比的话,就相当于盒子 ...
- vue2.0 网页标题更新实现思路
一.注册全局指令 1.注册一个全局指令 Vue.directive('title', { inserted: function (el, binding) { document.title = el. ...
- sqoop使用的问题
找不到表 17/05/02 18:15:47 ERROR tool.ImportTool: Imported Failed: There is no column found in the targe ...
- Linux入门之常用命令(13) date
在linux shell编程中,经常用到日期的加减运算 以前都是自己通过expr函数计算,很麻烦 其实date命令本身提供了日期的加减运算 非常方便.例如:得到昨天的时间date +%Y%m%d -- ...
- hdu 5937 -- Equation(搜索)
题目链接 problem description Little Ruins is a studious boy, recently he learned addition operation! He ...
- 分布式系统中生成全局ID的总结与思考
世间万物,都有自己唯一的标识,比如人,每个人都有自己的指纹(白夜追凶给我科普的,同卵双胞胎DNA一样,但指纹不一样).又如中国人,每个中国人有自己的身份证.对于计算机,很多时候,也需要为每一份数据生成 ...
- bzoj2257 [Jsoi2009]瓶子和燃料 最大公约数
[Jsoi2009]瓶子和燃料 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1449 Solved: 889[Submit][Status][Di ...