5

不久前,我从 akka-http 切换到 http4s。我想做正确的基本事情之一——JSON 处理,特别是发送 JSON 响应。

我决定使用带有 ZIO 的 http4s 而不是猫,所以下面是 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?

4

2 回答 2

7

是的,有:为任务定义和编码器和解码器:

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

于 2019-05-23T11:22:04.420 回答
1

对此还有更简单的解决方案。如果要处理 HTTP 响应的案例类 JSON 编码,只需添加以下导入:

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

顺便说一句,相同的导入也将传入的 JSON 请求解码为案例类

于 2019-06-12T16:51:06.900 回答