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

1656512889 kak nemarshalirovat json v akka http s pomoshhyu circe

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

lPAhIUMqAAGRGfHCcXzs2NgAVsFHwQUm3hvN

Несмотря на то, что обычная библиотека для (не)марширования JSON в приложениях Akka HTTP является spray-json, я решил попробовать. Я использую его в курсе Akka HTTP для начинающих, над которым работаю. *кашель* это бесплатно? *вой*

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

Чтобы использовать circe с Akka HTTP и другими библиотеками JSON, если на то пошло, мы должны создать вручную маршалеры и демаршалеры. К счастью есть дополнительная библиотека, которая уже делает это для нас.

Настройка и обзор проекта

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

под src/main/scala вы найдете следующие файлы:

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

The Main объект является точкой входа программы. Пока он имеет маршрут hello world и привязывает его к данному хосту и маршруту.

Todo это модель нашей программы. И TodoRepository отвечает за сохранение и доступ ко всем. Пока что у него только реализация в памяти, чтобы все было простым и сосредоточенным.

Список всех задач

Мы изменим 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)}

Сейчас мы слушаем запросы под /todos и мы отвечаем всем задачам, которые у нас есть todoRepository.

Однако если мы попытаемся запустить это, он не будет компилироваться:

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

Ошибка компиляции гласит нам, что она не знает, как маршировать наши задачки в JSON.

Нам нужно импортировать 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())  }}

С помощью этих двух дополнительных строк мы можем запустить наш Main объект и протестируйте наш новый маршрут.

Сделайте запрос GET к :

xuRxZ8giASz62AEFcSr0SZRIVRlXXOEoMZqL

И мы возвращаем свои дела! ?

Создание задач

Оказывается, что марширование JSON в наши модели также не требует особого труда. Но наш 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  }}

Мы добавили метод save к черте и реализации. Потому что мы используем a Vector наша реализация save будет сохранять дублированные задачи. Это хорошо для целей этого учебника.

Давайте добавим новый маршрут, который будет прослушивать запросы POST. Этот маршрут получают Todo как тело запроса и хранит его в нашем хранилище:

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

Использование entity директивы мы можем построить маршрут, который автоматически анализирует входящий JSON в нашу модель. Он также отклоняет запросы с недействительным JSON:

ew2sqvGf4H8BuBFuDM5iVG-RQsHTV5DVd9yx

Мы отправили done поле как строка, и оно должно быть логичным, на что наш API ответил плохим запросом.

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

qqLEGI-7ia2pcDesaClXCoTW7D21h5DOC7v1

На этот раз мы послали имущество как done := falseкоторый сообщает HTTPie отправлять значение как Boolean вместо String.

Мы получаем нашу задачу и код статуса 200, что означает, что все прошло хорошо. Мы можем подтвердить, что это сработало, снова спросив задачу:

bHQixnuljInXUXX7QaKPjX6JfX-9rm-Yxtln

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

Подведению

Мы добавили в программу маршалирования и демаршалирования JSON, добавив зависимости (это уже было сделано в проекте) и импортировав обе библиотеки.

Circe выясняет, как обращаться с нашими моделями без особого нашего вмешательства.

В следующей публикации мы рассмотрим, как выполнить ту же функциональность с помощью spray-json.

Следите за обновлениями!

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

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

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

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

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