Как правильно отправить ответ 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 в ответ?
1 ответ
Да, есть: определить и кодировщик и декодер для задачи:
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
HT: @mschuwalow
Для этого есть еще более простое решение. Если вы хотите обрабатывать кодировку JSON класса case для HTTP-ответов, вы можете просто добавить этот импорт:
import io.circe.generic.auto._
import org.http4s.circe.CirceEntityCodec._
Кстати, тот же импорт обрабатывает декодирование входящих запросов JSON в классы case