Добавить json body в http4s Запрос

Этот раздел показывает, как создать запрос http4s: https://http4s.org/v0.18/dsl/.

Я хотел бы изменить этот запрос на метод POST и добавить литеральное тело json, используя circe. Я попробовал следующий код:

val body = json"""{"hello":"world"}"""
val req = Request[IO](method = Method.POST, uri = Uri.uri("/"), body = body)

Это дает мне ошибку несоответствия типов:

[error]  found   : io.circe.Json
[error]  required: org.http4s.EntityBody[cats.effect.IO]
[error]     (which expands to)  fs2.Stream[cats.effect.IO,Byte]
[error]     val entity: EntityBody[IO] = body

Я понимаю ошибку, но я не могу понять, как конвертировать io.circe.Json в EntityBody, Большинство примеров, которые я видел, используют EntityEncoder, который не обеспечивает требуемый тип.

Как я могу конвертировать io.circe.Json в EntityBody?

1 ответ

Решение

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

import org.http4s.circe._

val body = json"""{"hello":"world"}"""
val req = Request[IO](method = Method.POST, uri = Uri.uri("/"))
  .withBody(body)
  .unsafeRunSync()

Объяснение:

Параметр body по запросу класс имеет тип EntityBody[IO] который является псевдонимом для Stream[IO, Byte], Вы не можете напрямую назначить ему объект String или Json, вам нужно использовать withBody метод вместо.

withBody принимает неявное EntityEncoder Например, ваш комментарий о нежелании использовать EntityEncoder не имеет смысла - вы должны использовать один, если вы не хотите создавать поток байтов самостоятельно. Тем не менее, библиотека http4s имеет предопределенные для ряда типов, и один для типа Json живет в org.http4s.circe._, Отсюда и утверждение импорта.

Наконец, вам нужно позвонить .unsafeRunSync() здесь, чтобы вытащить Request объект, потому что withBody возвращает IO[Request[IO]], Конечно же, лучший способ справиться с этим - связать результат с другими IO операции.

Начиная с http4s 20.0, withEntity перезаписывает существующее тело (по умолчанию пустое) новым телом. EntityEncoder все еще требуется, и может быть найден с импортом org.http4s.circe._:

import org.http4s.circe._

val body = json"""{"hello":"world"}"""

val req = Request[IO](
  method = Method.POST,
  uri = Uri.uri("/")
)
.withEntity(body)
Другие вопросы по тегам