博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
io.circe_如何使用Circe(Un)在Akka HTTP中封送JSON
阅读量:2520 次
发布时间:2019-05-11

本文共 6972 字,大约阅读时间需要 23 分钟。

io.circe

by Miguel Lopez

由Miguel Lopez

如何使用Circe(Un)在Akka HTTP中封送JSON (How to (Un)marshal JSON in Akka HTTP with Circe)

Even though the usual library to (un)marshal JSON in Akka HTTP applications is spray-json, I decided to give circe a try. I use it in the Akka HTTP beginners course I’m working on. *cough* ? *cough*

即使在Akka HTTP应用程序中用于(取消)封送JSON的常用库是spray-json,我还是决定尝试一下。 我正在研究的Akka HTTP初学者课程中使用它。 * 咳嗽 * 吗? * 咳嗽*

In this post I’d like to show you why I tried it out.

在这篇文章中,我想向您展示为什么我尝试了它。

To use circe with Akka HTTP — and other JSON libraries for that matter — we have to create the marshalers and unmarshalers manually. Thankfully, there is an that already does that for us.

要将circe与Akka HTTP以及其他JSON库一起使用,我们必须手动创建封送程序和取消封送程序。 值得庆幸的是,已经有一个已经为我们做到了。

项目设置和概述 (Project setup and overview)

Clone the , and checkout the branch 3.3-repository-implementation.

克隆 ,然后检出branch 3.3-repository-implementation

Under src/main/scala you'll find the following files:

src/main/scala您将找到以下文件:

$ tree srcsrc└── main    └── scala        ├── Main.scala        ├── Todo.scala        └── TodoRepository.scala2 directories, 3 files

The Main object is the application's entry point. So far it has a hello world route and it binds it to a given host and route.

Main对象是应用程序的入口点。 到目前为止,它具有问候世界路由,并将其绑定到给定的主机和路由。

Todo is our application’s model. And the TodoRepository is in charge of persisting and accessing todos. So far it only has an in-memory implementation to keep things simple and focused.

Todo是我们应用程序的模型。 TodoRepository负责持久化和访问待办事项。 到目前为止,它只有一个内存实现来使事情简单和集中。

列出所有待办事项 (Listing all the todos)

We’ll change the Main object’s route to list all the todos in a repository. We will also add some initial todos for testing:

我们将更改Main对象的路由以列出存储库中的所有待办事项。 我们还将添加一些初始待办事项进行测试:

import akka.actor.ActorSystemimport akka.http.scaladsl.Httpimport akka.stream.ActorMaterializerimport scala.concurrent.Awaitimport scala.util.{Failure, Success}object Main extends App {  val host = "0.0.0.0"  val port = 9000  implicit val system: ActorSystem = ActorSystem(name = "todoapi")  implicit val materializer: ActorMaterializer = ActorMaterializer()  import system.dispatcher  val todos = Seq(    Todo("1", "Clean the house", "", done = false),    Todo("2", "Learn Scala", "", done = true),  )  val todoRepository = new InMemoryTodoRepository(todos)  import akka.http.scaladsl.server.Directives._  def route = path("todos") {    get {      complete(todoRepository.all())    }  }  val binding = Http().bindAndHandle(route, host, port)  binding.onComplete {    case Success(_) => println("Success!")    case Failure(error) => println(s"Failed: ${error.getMessage}")  }  import scala.concurrent.duration._  Await.result(binding, 3.seconds)}

Now we’re listening to requests under /todos and we respond with all the todos we have in our todoRepository.

现在,我们正在侦听/todos下的请求,并使用todoRepository所有todo进行响应。

However, if we try to run this it won’t compile:

但是,如果我们尝试运行此命令,它将无法编译:

Error:(26, 34) type mismatch; found   : scala.concurrent.Future[Seq[Todo]] required: akka.http.scaladsl.marshalling.ToResponseMarshallable      complete(todoRepository.all())

The compilation error is telling us it doesn’t know how to marshal our todos into JSON.

编译错误告诉我们它不知道如何将待办事项编组为JSON。

We need to import circe and the support library:

我们需要导入circe和支持库:

import akka.http.scaladsl.server.Directives._import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport._import io.circe.generic.auto._def route = path("todos") {  get {    complete(todoRepository.all())  }}

With those two extra lines we can now run our Main object and test our new route.

通过这两行,我们现在可以运行Main对象并测试新路线。

Make a GET request to http://localhost:9000/todos :

http://localhost:9000/todos发出GET请求:

And we get our todos back! ?

而且我们还可以得到待办事项! ?

创建待办事项 (Creating todos)

Turns out that unmarshaling JSON into our models doesn’t take much effort either. But our TodoRepository doesn’t support saving todos at the moment. Let’s add that functionality first:

事实证明,将JSON编组到我们的模型中也不需要太多的工作。 但是我们的TodoRepository目前不支持保存TodoRepository 。 让我们先添加该功能:

import scala.concurrent.{ExecutionContext, Future}trait TodoRepository {  def all(): Future[Seq[Todo]]  def done(): Future[Seq[Todo]]  def pending(): Future[Seq[Todo]]  def save(todo: Todo): Future[Todo]}class InMemoryTodoRepository(initialTodos: Seq[Todo] = Seq.empty)(implicit ec: ExecutionContext) extends TodoRepository {  private var todos: Vector[Todo] = initialTodos.toVector  override def all(): Future[Seq[Todo]] = Future.successful(todos)  override def done(): Future[Seq[Todo]] = Future.successful(todos.filter(_.done))  override def pending(): Future[Seq[Todo]] = Future.successful(todos.filterNot(_.done))  override def save(todo: Todo): Future[Todo] = Future.successful {    todos = todos :+ todo    todo  }}

We added a method save to the trait and the implementation. Because we are using a Vector our implementation of save will store duplicated todos. That’s fine for the purposes of this tutorial.

我们向特征和实现添加了save方法。 因为我们使用的是Vector ,所以save的实现将存储重复的待办事项。 就本教程而言,这很好。

Let’s add a new route that will listen to POST requests. This route receive a Todo as the request’s body and saves it into our repository:

让我们添加一条新的路由来监听POST请求。 此路由将Todo作为请求的主体,并将其保存到我们的存储库中:

def route = path("todos") {  get {    complete(todoRepository.all())  } ~ post {    entity(as[Todo]) { todo =>      complete(todoRepository.save(todo))    }  }}

Using the entity directive we can build a route that automatically parses incoming JSON to our model. It also rejects requests with invalid JSON:

使用entity指令,我们可以构建一个路由,该路由自动将传入的JSON解析到我们的模型。 它还拒绝使用无效JSON的请求:

We sent the done field as a string, and it should have been a boolean, which our API responded to with bad request.

我们以字符串形式发送了done字段,它应该是一个布尔值,我们的API响应该请求时发出了错误请求。

Let’s make a valid request to create a new todo:

让我们发出一个有效的请求来创建一个新的待办事项:

This time we sent the property as done := false, which tells HTTPie to send the value as Boolean instead of String.

这次我们将属性发送为done := false ,这告诉HTTPie将值作为Boolean而不是String

We get our todo back and a 200 status code, which means it went well. We can confirm it worked by querying the todos again:

我们找回待办事项和200状态代码,这意味着一切顺利。 我们可以通过再次查询待办事项来确认它是否有效:

We get three todos, the hardcoded ones and the new one we created.

我们得到三个待办事项,分别是硬编码和新创建的。

结语 (Wrapping up)

We added JSON marshaling and unmarshaling to our application by adding the dependencies (it was already done in the project) and by importing both libraries.

通过添加依赖项(已经在项目中完成)并导入两个库,我们在应用程序中添加了JSON封送处理和取消封送处理。

Circe figures out how to handle our models without much intervention from us.

Circe指出了如何在没有太多干预的情况下处理我们的模型。

In a future post, we will explore how to accomplish the same functionality with spray-json instead.

在以后的文章中,我们将探索如何使用spray-json来实现相同的功能。

Stay tuned!

敬请关注!

If you liked this tutorial and want to learn how to build an API for a todo application, check out our new free course! ???

如果您喜欢本教程,并且想学习如何为待办事项应用程序构建API,请查看我们的新免费课程! ???

Originally published at .

最初在发布。

翻译自:

io.circe

转载地址:http://hdewd.baihongyu.com/

你可能感兴趣的文章
mysql存储过程使用游标循环插入数据
查看>>
Ubuntu 12.04 添加新用户并启用root登录
查看>>
20145309信息安全系统设计基础第9周学习总结上
查看>>
c# 字段、属性get set
查看>>
td内容超出隐藏
查看>>
Spring CommonsMultipartResolver 上传文件
查看>>
Settings app简单学习记录
查看>>
SQLAlchemy
查看>>
多线程
查看>>
使用缓存的9大误区(下)转载
查看>>
appium键值对的应用
查看>>
MyEclipse 8.X 通用算法
查看>>
selenium.Phantomjs设置浏览器请求头
查看>>
分布式数据库如何选择,几种分布式数据库优缺点一览
查看>>
BZOJ 4443: 小凸玩矩阵【二分图】
查看>>
苹果 OS X制作u盘启动盘
查看>>
Jquery便利对象
查看>>
MVC: Connection String
查看>>
idea常用设置汇总
查看>>
Node.SelectNodes
查看>>