Как (не)маршалировать JSON в Akka HTTP с помощью spray-json

1656537850 kak nemarshalirovat json v akka http s pomoshhyu spray json

от Мигеля Лопеса

9JletIAmWZ7lY4gIiEj1nO4AR0s8RlKPNBWi

В предыдущей публикации мы добавили поддержку JSON к нашему Akka HTTP API с помощью circe.

На этот раз мы сделаем то же самое, но с помощью spray-json. Akka HTTP поддерживает это, предоставляя официальную библиотеку – нам не нужна сторонняя библиотека, как это было с circe.

Настройка проекта

Для настройки проекта мы выполним те же шаги, что и в предыдущем руководстве.

Клонируйте репо и проверьте ветку 3.3-repository-implementation.

Мы также внесем изменения, которые были внесены в предыдущем учебнике.

Сначала мы заменим зависимость circe на зависимость spray-json, поскольку она нам не понадобится для этого учебника. Обновите build.sbt файл с таким содержимым:

name := "akkahttp-quickstart"version := "0.1"scalaVersion := "2.12.6"val akkaVersion = "2.5.13"val akkaHttpVersion = "10.1.3"libraryDependencies ++= Seq(  "com.typesafe.akka" %% "akka-actor" % akkaVersion,  "com.typesafe.akka" %% "akka-testkit" % akkaVersion % Test,  "com.typesafe.akka" %% "akka-stream" % akkaVersion,  "com.typesafe.akka" %% "akka-stream-testkit" % akkaVersion % Test,  "com.typesafe.akka" %% "akka-http" % akkaHttpVersion,  "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion % Test,  "com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion,  "org.scalatest" %% "scalatest" % "3.0.5" % Test)

Далее мы добавим a save функция до 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  }}

Это позволит создать запрос POST для создания новых задач.

И, наконец, обновите 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", "Record amazing gifs for the tutorials", "", done = false),    Todo("2", "Finish the spray-json tutorial", "", done = true),  )  val todoRepository = new InMemoryTodoRepository(todos)  import akka.http.scaladsl.server.Directives._  def route = path("todos") {    get {      complete(todoRepository.all())    } ~ post {      entity(as[Todo]) { todo =>        complete(todoRepository.save(todo))      }    }  }  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)}

После этого мы можем перейти к поддержке анализа JSON.

Создание формата

Проект не должен компилироваться сейчас, потому что Akka HTTP не знает, как конвертировать JSON в наши модели и наоборот.

Добавить поддержку JSON с помощью circe было достаточно просто. Это включало только добавление нескольких операторов импорта.

К сожалению, из spray-json это не так. Усилия тоже не так велики.

Итак, начнём.

Поскольку мы хотим использовать spray-json из Akka HTTP, мы можем просмотреть официальные документы Akka HTTP о том, как добиться того, что мы хотим.

Нам нужно расширить черту SprayJsonSupport чтобы дать Akka HTTP знать, как анализировать наши модели в и из JSON (через файл FromEntityUnmarshaller и ToEntityMarshaller обеспечивается признаком).

И создать актуальное форматмы будем использовать признак DefaultJsonProtocol из spray-json.

Добавьте следующий объект под Todo модель:

object TodoFormat extends SprayJsonSupport with DefaultJsonProtocol {  implicit val todoFormat = jsonFormat4(Todo)}

Это дополнительный шаг, который нам необходим при использовании spray-json. Это нужно сделать для каждой модели, которую у нас есть.

Чтобы наш проект заработал, нам нужно импортировать TodoFormat в нашем Main объект:

import TodoFormat._import akka.http.scaladsl.server.Directives._def route = path("todos") {  get {    complete(todoRepository.all())  } ~ post {    entity(as[Todo]) { todo =>      complete(todoRepository.save(todo))    }  }}

Запустите программу, и она должна работать нормально.

Давайте проведем несколько тестов!

Тестирование нашего API

Нам нужно убедиться, что наш API работает должным образом. Давайте спросим его, как мы делали в предыдущем учебнике, чтобы проверить, функциональность такая же.

Отправка запроса GET в localhost:9000/todos должно дать нам первоначальные задачи:

97TXx4zg12xaNIhdDcxZys0figQgN06hFTdI

Прекрасно, это работает так же.

Давайте посмотрим, дает ли нам отправка недействительного JSON что-то подобное:

SeH1uiH0xzKy12LYxYIglHDS8TmWIlZ8kifl

Это делает. Сообщение об ошибке разное, но мы получаем то же 400 Bad Request что является важной частью.

Давайте создадим новое задание с действительным JSON:

o3ItlFqvXdih41ioeLPP7p9VI1F3ZpXu23fm

И чтобы кончить, давайте еще раз спросим todos, чтобы убедиться, что они сохранены:

q9BNV8IqdeXQ-FMBp1q6rtaD9Ef9M2sZKVbG

Там мы уходим. У нас есть рабочая программа с spray-json.

Круто, не правда ли?

Подведению

Несмотря на то, что работа с spray-json подразумевает дополнительную ручную работу, вам не нужна дополнительная зависимость от сторонних разработчиков, чтобы заставить его работать с Akka HTTP.

Это действительно вопрос преимуществ.

В будущем мы будем исследовать, как выполнить различные варианты использования для обоих, чтобы сравнить их. Следите за обновлением!

Если вам понравилось это руководство и вы хотите узнать, как создать API для программы Todo, просмотрите наш новый бесплатно конечно! ???

Akka HTTP Quickstart
Узнайте, как создать веб-приложения и API с помощью Akka HTTP в этом бесплатном курсе!link.codemunity.io

Первоначально опубликовано на www.codemunity.io.

Добавить комментарий

Ваш адрес email не будет опубликован.