Как правильно отправить ответ JSON в http4s?

Не так давно я перешел с akka-http на http4s. Одна из базовых вещей, которую я хотел сделать правильно — обработка JSON, в частности отправка JSON-ответа.

Я решил использовать http4s с ZIO вместо котов, вот как выглядит http-маршрут:

import fs2.Stream
import org.http4s._
import org.http4s.dsl.io._
import org.http4s.implicits._
import scalaz.zio.Task
import scalaz.zio.interop.catz._
import io.circe.generic.auto._
import io.circe.syntax._

class TweetsRoutes {

  case class Tweet(author: String, tweet: String)

  val helloWorldService = HttpRoutes.of[Task] {
    case GET -> Root / "hello" / name => Task {
      Response[Task](Ok)
        .withBodyStream(Stream.emits(
          Tweet(name, "dummy tweet text").asJson.toString.getBytes
        ))
    }
  }.orNotFound

}

Как видите, часть сериализации JSON довольно многословна:

.withBodyStream(Stream.emits(
  Tweet(name, "dummy tweet text").asJson.toString.getBytes
))

Есть ли другой способ отправить JSON в ответ?


person Alex Fruzenshtein    schedule 23.05.2019    source источник


Ответы (2)


Да, есть: определить и кодировщик и декодер для задачи:

implicit def circeJsonDecoder[A](
      implicit decoder: Decoder[A]
  ): EntityDecoder[Task, A] = jsonOf[Task, A]
  implicit def circeJsonEncoder[A](
      implicit encoder: Encoder[A]
  ): EntityEncoder[Task, A] = jsonEncoderOf[Task, A]

таким образом нет необходимости преобразовывать в байты.

РЕДАКТИРОВАТЬ: здесь есть полный пример: https://github.com/mschuwalow/zio-todo-backend/blob/develop/src/main/scala/com/schuwalow/zio/todo/http/TodoService.scala< /а>

ХТ: @mschuwalow

person toxicafunk    schedule 23.05.2019

Для этого есть еще более простое решение. Если вы хотите обрабатывать кодировку JSON класса case для ответов HTTP, вы просто можете добавить эти импорты:

import io.circe.generic.auto._
import org.http4s.circe.CirceEntityCodec._

Кстати, тот же самый импорт также обрабатывает декодирование входящих запросов JSON в классы case.

person Alex Fruzenshtein    schedule 12.06.2019