Endpoints JSON
Combine http4s con Circe
Endpoints JSON es una lección gratuita de Scala for Backend Engineering & Functional Programming en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Scala for Backend Engineering & Functional Programming, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Scala for Backend Engineering & Functional Programming incluye 4 lecciones en total.
JSON mediante circe
http4s integra JSON mediante el módulo http4s-circe, que conecta los codecs de circe con EntityDecoder y EntityEncoder. circe es la biblioteca JSON funcional de facto para Scala.
Defina instancias de Encoder y Decoder para sus tipos y deje que http4s gestione el formato de transmisión.
// build.sbt
// "org.http4s" %% "http4s-circe" % http4sV
// "io.circe" %% "circe-generic" % circeVDerivación de codecs
Con circe-generic puede derivar codecs automáticamente mediante deriveEncoder/deriveDecoder o la anotación @JsonCodec. Estos asocian los campos de las case classes con las claves JSON por nombre.
La derivación necesita codecs para todos los tipos de los campos, de forma recursiva.
import io.circe.generic.semiauto._
case class User(id: Int, name: String)
implicit val enc = deriveEncoder[User]
implicit val dec = deriveDecoder[User]EntityEncoder de circe
La importación org.http4s.circe.CirceEntityEncoder._ proporciona un EntityEncoder[F, A] implícito para cualquier A que tenga un Encoder de circe. Entonces Ok(user) se serializa como JSON con application/json.
No es necesario convertir manualmente el valor a Json en los handlers.
import org.http4s.circe.CirceEntityEncoder._
HttpRoutes.of[IO] {
case GET -> Root / "me" => Ok(User(1, "Ada"))
}EntityDecoder de circe
Es la operación inversa: org.http4s.circe.CirceEntityDecoder._ proporciona un EntityDecoder[F, A] para cualquier A que tenga un Decoder de circe. Entonces req.as[User] analiza el cuerpo JSON.
Ambas importaciones juntas se agrupan como CirceEntityCodec._.
import org.http4s.circe.CirceEntityDecoder._
case req @ POST -> Root / "users" =>
req.as[User].flatMap(u => Created(u))Un POST JSON completo
Combinar la decodificación y la codificación permite crear un endpoint limpio: analice el JSON entrante como un tipo de dominio, ejecute la lógica de negocio y vuelva a codificar el resultado como JSON.
Los errores de decodificación aparecen como 422 o 400 mediante el decoder de circe.
import org.http4s.circe.CirceEntityCodec._
case req @ POST -> Root / "users" =>
for {
in <- req.as[User]
out <- store.create(in)
res <- Created(out)
} yield resEl interpolador json
Para JSON puntual, el interpolador de cadenas json de circe, procedente de io.circe.literal, construye directamente un valor Json con valores de Scala interpolados.
Es útil para respuestas pequeñas o datos de prueba sin una case class.
import io.circe.literal._
val body = json"""{ "status": "ok", "count": 3 }"""
Ok(body)Nombres de campos personalizados
Cuando las claves JSON difieren de los nombres de los campos de Scala, derive el codec con una Configuration de circe-generic-extras, por ejemplo snake_case, o escríbalo manualmente con forProduct2.
Esto desacopla el contrato de su API de los nombres internos.
import io.circe.Encoder
implicit val e: Encoder[User] =
Encoder.forProduct2("user_id", "full_name")(u => (u.id, u.name))Codificación de listas
circe proporciona automáticamente codecs para List, Vector, Option y Map una vez que existe el codec de los elementos. Por tanto, devolver una colección funciona directamente.
Una lista vacía se codifica como [] y None como una clave ausente o como null.
import org.http4s.circe.CirceEntityEncoder._
case GET -> Root / "users" =>
store.all.flatMap(us => Ok(us)) // List[User] -> JSON arrayValidación del JSON decodificado
La decodificación le proporciona un valor sintácticamente válido; la validación semántica es responsabilidad suya. Ejecute las comprobaciones después de as y detenga el procesamiento con BadRequest cuando el valor no sea válido.
Mantenga las invariantes del dominio en constructores inteligentes que devuelvan Either para mayor claridad.
req.as[User].flatMap { u =>
if (u.name.nonEmpty) Created(u)
else BadRequest("name required")
}Respuestas de error como JSON
Devuelva los errores estructurados como JSON para que los clientes puedan analizarlos. Defina una clase de caso para el error con un codificador de circe y pásela al constructor de estado correspondiente.
Las estructuras de error coherentes hacen que las API sean mucho más fáciles de consumir.
case class ApiError(code: String, message: String)
implicit val e = deriveEncoder[ApiError]
BadRequest(ApiError("E_NAME", "name required"))Transmisión de JSON
Para colecciones grandes, puede transmitir el JSON en lugar de almacenarlo en un búfer. jsonEncoderOf junto con un Stream[F, A] de fs2 emite un array JSON de forma incremental.
Esto mantiene estable el uso de memoria para conjuntos de resultados grandes y aprovecha el control de presión de fs2.
import org.http4s.circe.streamJsonArrayEncoder
case GET -> Root / "feed" =>
Ok(store.streamAll) // fs2.Stream[IO, Event]Comprobación rápida
Recuerde qué import permite decodificar un cuerpo JSON en una clase de caso.
Resumen
Configuró JSON con http4s-circe: derivó códecs, importó CirceEntityCodec y usó Ok(value) / req.as[A] para gestionar completamente la entrada y salida de JSON.
Gestionó listas, nombres de campos personalizados y errores JSON estructurados, e incluso arrays transmitidos para cargas grandes.
Preguntas frecuentes
¿La lección «Endpoints JSON» es gratis?
Sí — el texto completo de «Endpoints JSON» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Scala for Backend Engineering & Functional Programming, actualiza a CoddyKit PRO. El curso de Scala for Backend Engineering & Functional Programming incluye 4 lecciones en total.
¿Qué aprenderé en «Endpoints JSON»?
Combine http4s con Circe Practicas Scala for Backend Engineering & Functional Programming con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Scala for Backend Engineering & Functional Programming?
No se requiere experiencia previa. Scala for Backend Engineering & Functional Programming en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Endpoints JSON»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Scala for Backend Engineering & Functional Programming?
Sí. Cada lección de Scala for Backend Engineering & Functional Programming incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.