0Pricing
Scala for Backend Engineering & Functional Programming · Lezione

Endpoint JSON

Combini http4s con Circe.

Endpoint JSON è una lezione Scala for Backend Engineering & Functional Programming gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Scala for Backend Engineering & Functional Programming, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Scala for Backend Engineering & Functional Programming include 4 lezioni in totale.

JSON con circe

http4s integra JSON tramite il modulo http4s-circe, che collega i codec di circe a EntityDecoder e EntityEncoder. circe è di fatto la libreria JSON funzionale di riferimento per Scala.

Si definiscono istanze di Encoder e Decoder per i propri tipi e si lascia che http4s gestisca il formato sul filo.

// build.sbt
// "org.http4s" %% "http4s-circe" % http4sV
// "io.circe"   %% "circe-generic" % circeV

Derivazione dei codec

Con circe-generic si derivano automaticamente i codec usando deriveEncoder/deriveDecoder oppure l’annotazione @JsonCodec. I campi delle case class vengono associati alle chiavi JSON in base al nome.

La derivazione richiede ricorsivamente codec per il tipo di ogni campo.

import io.circe.generic.semiauto._

case class User(id: Int, name: String)
implicit val enc = deriveEncoder[User]
implicit val dec = deriveDecoder[User]

EntityEncoder da circe

L’import org.http4s.circe.CirceEntityEncoder._ fornisce un EntityEncoder[F, A] implicito per ogni A che dispone di un Encoder di circe. In questo modo Ok(user) viene serializzato in JSON con application/json.

Nei gestori non è necessaria alcuna conversione manuale in Json.

import org.http4s.circe.CirceEntityEncoder._

HttpRoutes.of[IO] {
  case GET -> Root / "me" => Ok(User(1, "Ada"))
}

EntityDecoder da circe

È il procedimento inverso: org.http4s.circe.CirceEntityDecoder._ fornisce un EntityDecoder[F, A] per ogni A che dispone di un Decoder di circe. Quindi req.as[User] analizza il body JSON.

Entrambi gli import sono disponibili insieme tramite CirceEntityCodec._.

import org.http4s.circe.CirceEntityDecoder._

case req @ POST -> Root / "users" =>
  req.as[User].flatMap(u => Created(u))

Un POST JSON completo

Combinare decoding ed encoding permette di creare un endpoint di creazione chiaro: si analizza il JSON ricevuto in un tipo di dominio, si esegue la logica applicativa e poi si codifica nuovamente il risultato come JSON.

Gli errori di decoding vengono restituiti come 422 o 400 tramite il decoder di circe.

import org.http4s.circe.CirceEntityCodec._

case req @ POST -> Root / "users" =>
  for {
    in  <- req.as[User]
    out <- store.create(in)
    res <- Created(out)
  } yield res

L’interpolatore json

Per JSON ad hoc, l’interpolatore di stringhe json di circe, proveniente da io.circe.literal, costruisce direttamente un valore Json con valori Scala interpolati.

È utile per piccole risposte o fixture di test quando non si dispone di una case class.

import io.circe.literal._

val body = json"""{ "status": "ok", "count": 3 }"""
Ok(body)

Nomi dei campi personalizzati

Quando le chiavi JSON differiscono dai nomi dei campi Scala, si può derivare il codec con una Configuration di circe-generic-extras, ad esempio snake_case, oppure scriverlo manualmente usando forProduct2.

In questo modo il contratto dell’API resta indipendente dalla nomenclatura interna.

import io.circe.Encoder

implicit val e: Encoder[User] =
  Encoder.forProduct2("user_id", "full_name")(u => (u.id, u.name))

Codifica delle liste

circe fornisce automaticamente codec per List, Vector, Option e Map non appena esiste il codec degli elementi. Restituire una collezione funziona quindi senza configurazioni aggiuntive.

Una lista vuota viene codificata come [] e None come chiave assente oppure null.

import org.http4s.circe.CirceEntityEncoder._

case GET -> Root / "users" =>
  store.all.flatMap(us => Ok(us)) // List[User] -> JSON array

Validazione del JSON decodificato

Il decoding restituisce un valore sintatticamente valido; la validazione semantica spetta a Lei. Esegua i controlli dopo as e interrompa il flusso con BadRequest quando il valore non è valido.

Mantenga gli invarianti del dominio in smart constructor che restituiscono Either, per maggiore chiarezza.

req.as[User].flatMap { u =>
  if (u.name.nonEmpty) Created(u)
  else BadRequest("name required")
}

Risposte di errore come JSON

Restituisca gli errori strutturati come JSON, così i client possono analizzarli. Definisca una case class per l’errore con un encoder di circe e la passi al builder dello status appropriato.

Strutture di errore coerenti rendono le API molto più semplici da utilizzare.

case class ApiError(code: String, message: String)
implicit val e = deriveEncoder[ApiError]

BadRequest(ApiError("E_NAME", "name required"))

JSON in streaming

Per collezioni di grandi dimensioni è possibile trasmettere il JSON in streaming invece di inserirlo tutto in memoria. jsonEncoderOf insieme a uno Stream[F, A] di fs2 emette progressivamente un array JSON.

In questo modo la memoria utilizzata rimane costante anche per grandi insiemi di risultati, sfruttando il back-pressure di fs2.

import org.http4s.circe.streamJsonArrayEncoder

case GET -> Root / "feed" =>
  Ok(store.streamAll) // fs2.Stream[IO, Event]

Verifica rapida

Ricordi quale import abilita il decoding di un body JSON in una case class.

Riepilogo

Ha configurato JSON con http4s-circe: ha derivato i codec, importato CirceEntityCodec e usato Ok(value) / req.as[A] per l’I/O JSON completo.

Ha gestito liste, nomi di campo personalizzati, errori JSON strutturati e persino array in streaming per payload di grandi dimensioni.

Domande Frequenti

La lezione «Endpoint JSON» è gratuita?

Sì — il testo completo di «Endpoint JSON» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Scala for Backend Engineering & Functional Programming, passa a CoddyKit PRO. Il corso Scala for Backend Engineering & Functional Programming include 4 lezioni in totale.

Cosa imparerò in «Endpoint JSON»?

Combini http4s con Circe. Eserciti Scala for Backend Engineering & Functional Programming con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Scala for Backend Engineering & Functional Programming?

Non è richiesta alcuna esperienza precedente. Scala for Backend Engineering & Functional Programming su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «Endpoint JSON»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Scala for Backend Engineering & Functional Programming?

Sì. Ogni lezione Scala for Backend Engineering & Functional Programming include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Route e HttpRoutes
  2. Richieste e risposte
  3. Endpoint JSON
  4. Servire l'applicazione
← Torna a Scala for Backend Engineering & Functional Programming