Endpoints JSON
Combine http4s com Circe.
Endpoints JSON é uma aula grátis de Scala for Backend Engineering & Functional Programming no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Scala for Backend Engineering & Functional Programming, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.
Partes desta aula ainda não foram traduzidas e aparecem em inglês.
JSON via circe
http4s integrates JSON through the http4s-circe module, which bridges circe codecs to EntityDecoder and EntityEncoder. circe is the de facto functional JSON library for Scala.
You define Encoder and Decoder instances for your types and let http4s handle the wire format.
// build.sbt
// "org.http4s" %% "http4s-circe" % http4sV
// "io.circe" %% "circe-generic" % circeVDeriving Codecs
With circe-generic you derive codecs automatically using deriveEncoder/deriveDecoder or the @JsonCodec annotation. They map case-class fields to JSON keys by name.
Derivation needs codecs for every field type, recursively.
import io.circe.generic.semiauto._
case class User(id: Int, name: String)
implicit val enc = deriveEncoder[User]
implicit val dec = deriveDecoder[User]EntityEncoder from circe
The import org.http4s.circe.CirceEntityEncoder._ provides an implicit EntityEncoder[F, A] for any A with a circe Encoder. Then Ok(user) serializes to JSON with application/json.
No manual conversion to Json is needed in handlers.
import org.http4s.circe.CirceEntityEncoder._
HttpRoutes.of[IO] {
case GET -> Root / "me" => Ok(User(1, "Ada"))
}EntityDecoder from circe
Mirror image: org.http4s.circe.CirceEntityDecoder._ supplies an EntityDecoder[F, A] for any A with a circe Decoder. Then req.as[User] parses the JSON body.
Both imports together are bundled as CirceEntityCodec._.
import org.http4s.circe.CirceEntityDecoder._
case req @ POST -> Root / "users" =>
req.as[User].flatMap(u => Created(u))A Full JSON POST
Combining decode and encode gives a clean create endpoint: parse the incoming JSON to a domain type, run business logic, then encode the result back as JSON.
Decoding failures surface as 422 or 400 via the circe decoder.
import org.http4s.circe.CirceEntityCodec._
case req @ POST -> Root / "users" =>
for {
in <- req.as[User]
out <- store.create(in)
res <- Created(out)
} yield resThe json Interpolator
For ad hoc JSON, circe's json string interpolator from io.circe.literal builds a Json value directly, with interpolated Scala values.
Useful for small responses or test fixtures without a case class.
import io.circe.literal._
val body = json"""{ "status": "ok", "count": 3 }"""
Ok(body)Custom Field Names
When JSON keys differ from Scala field names, derive with a Configuration from circe-generic-extras, e.g. snake_case, or write the codec by hand using forProduct2.
This decouples your API contract from internal naming.
import io.circe.Encoder
implicit val e: Encoder[User] =
Encoder.forProduct2("user_id", "full_name")(u => (u.id, u.name))Encoding Lists
circe provides codecs for List, Vector, Option, and Map automatically once the element codec exists. So returning a collection just works.
An empty list encodes to [] and None to either an absent key or null.
import org.http4s.circe.CirceEntityEncoder._
case GET -> Root / "users" =>
store.all.flatMap(us => Ok(us)) // List[User] -> JSON arrayValidating Decoded JSON
Decoding gives you a syntactically valid value; semantic validation is yours. Run checks after as and short-circuit with BadRequest when invalid.
Keep domain invariants in smart constructors returning Either for clarity.
req.as[User].flatMap { u =>
if (u.name.nonEmpty) Created(u)
else BadRequest("name required")
}Error Responses as JSON
Return structured errors as JSON so clients can parse them. Define an error case class with a circe encoder and pass it to the relevant status builder.
Consistent error shapes make APIs far easier to consume.
case class ApiError(code: String, message: String)
implicit val e = deriveEncoder[ApiError]
BadRequest(ApiError("E_NAME", "name required"))Streaming JSON
For large collections you can stream JSON instead of buffering. jsonEncoderOf plus an fs2 Stream[F, A] emits a JSON array incrementally.
This keeps memory flat for big result sets, leveraging fs2 back-pressure.
import org.http4s.circe.streamJsonArrayEncoder
case GET -> Root / "feed" =>
Ok(store.streamAll) // fs2.Stream[IO, Event]Quick Check
Recall which import enables decoding a JSON body to a case class.
Recap
You wired JSON with http4s-circe: derive codecs, import CirceEntityCodec, and use Ok(value) / req.as[A] for full JSON I/O.
You handled lists, custom field names, structured JSON errors, and even streaming arrays for large payloads.
Perguntas Frequentes
A aula “Endpoints JSON” é grátis?
Sim — o texto completo de “Endpoints JSON” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Scala for Backend Engineering & Functional Programming, atualize para CoddyKit PRO. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.
O que vou aprender em “Endpoints JSON”?
Combine http4s com Circe. Você pratica Scala for Backend Engineering & Functional Programming com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Scala for Backend Engineering & Functional Programming?
Nenhuma experiência prévia é necessária. Scala for Backend Engineering & Functional Programming no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “Endpoints JSON”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Scala for Backend Engineering & Functional Programming?
Sim. Cada aula de Scala for Backend Engineering & Functional Programming inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.