简体   繁体   English

将json正文添加到http4s请求

[英]Add json body to http4s Request

This tut shows how to create an http4s Request: https://http4s.org/v0.18/dsl/#testing-the-service 这个tut展示了如何创建一个http4s请求: https ://http4s.org/v0.18/dsl/#testing-the-service

I would like to change this request to a POST method and add a literal json body using circe. 我想将此请求更改为POST方法并使用circe添加文字json正文。 I tried the following code: 我尝试了以下代码:

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

This gives me a type mismatch error: 这给了我一个类型不匹配的错误:

[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

I understand the error, but I cannot figure out how to convert io.circe.Json into an EntityBody . 我理解错误,但我无法弄清楚如何将io.circe.Json转换为EntityBody Most examples I have seen use an EntityEncoder , which does not provide the required type. 我见过的大多数示例都使用EntityEncoder ,它不提供所需的类型。

How can I convert io.circe.Json into an EntityBody ? 如何将io.circe.Json转换为EntityBody

Oleg's link mostly covers it, but here's how you'd do it for a custom request body: Oleg的链接主要涵盖它,但这里是你如何为自定义请求体做到这一点:

import org.http4s.circe._

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

Explanation: 说明:

The parameter body on the request class is of type EntityBody[IO] which is an alias for Stream[IO, Byte] . 请求类上的参数bodyEntityBody[IO]类型,它是Stream[IO, Byte]的别名。 You can't directly assign a String or Json object to it, you need to use the withBody method instead. 您不能直接为其指定String或Json对象,而是需要使用withBody方法。

withBody takes an implicit EntityEncoder instance, so your comment about not wanting to use an EntityEncoder doesn't make sense - you have to use one if you don't want to create a byte stream yourself. withBody采用隐式EntityEncoder实例,因此您不想使用EntityEncoder没有意义 - 如果您不想自己创建字节流,则必须使用它。 However, the http4s library has predefined ones for a number of types, and the one for type Json lives in org.http4s.circe._ . 但是,http4s库具有多种类型的预定义库,而Json类型的org.http4s.circe._org.http4s.circe._ Hence the import statement. 因此导入声明。

Lastly, you need to call .unsafeRunSync() here to pull out a Request object because withBody returns an IO[Request[IO]] . 最后,您需要在此处调用.unsafeRunSync()来提取Request对象,因为withBody返回IO[Request[IO]] The better way to handle this would of course be via chaining the result with other IO operations. 处理此问题的更好方法当然是通过将结果与其他IO操作链接起来。

As of http4s 20.0, withEntity overwrites the existing body (which defaults to empty) with the new body. 从http4s 20.0开始, withEntity用新主体覆盖现有主体(默认为空)。 The EntityEncoder is still required, and can be found with an import of org.http4s.circe._ : 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM