Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the right way to send JSON response in http4s?

Tags:

scala

http4s

zio

Not so long time ago I switched from akka-http to http4s. One of the basic things which I wanted to do correctly — JSON handling, in particular sending a JSON response.

I decided to use http4s with ZIO instead of cats, so here is how an http route looks like:

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

}

As you see, JSON serialization part is pretty verbose:

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

Is there any other way to send JSON in a response?

like image 633
Alex Fruzenshtein Avatar asked May 23 '19 10:05

Alex Fruzenshtein


2 Answers

Yes, there is: define and Encoder and Decoder for Task:

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]

this way there is no need to transform to bytes.

EDIT: there is a full example here: https://github.com/mschuwalow/zio-todo-backend/blob/develop/src/main/scala/com/schuwalow/zio/todo/http/TodoService.scala

HT: @mschuwalow

like image 63
toxicafunk Avatar answered Oct 18 '22 14:10

toxicafunk


There is even simpler solution for this. If you want to handle case class JSON encoding for HTTP responses, you just can add these imports:

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

BTW, the same imports handle decoding of incoming JSON requests into case classes as well

like image 1
Alex Fruzenshtein Avatar answered Oct 18 '22 16:10

Alex Fruzenshtein