0Pricing
Scala for Backend Engineering & Functional Programming · Lektion

Benutzerdefinierte Codecs

Behandeln Sie schwierige Strukturen.

Benutzerdefinierte Codecs ist eine kostenlose Scala for Backend Engineering & Functional Programming-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Scala for Backend Engineering & Functional Programming-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Scala for Backend Engineering & Functional Programming-Kurs umfasst insgesamt 4 Lektionen.

Wann Sie benutzerdefinierte Codecs benötigen

Die Ableitung deckt den häufigsten Fall ab, aber manchmal entspricht JSON nicht Ihrer Case-Klasse: etwa bei alten Feldnamen, codierten Enums oder Formaten wie Zeitstempeln.

Dann schreiben Sie einen Decoder, einen Encoder oder beide von Hand.

Ein Decoder aus einem Cursor

Die ausführlichste Möglichkeit, einen Decoder zu erstellen, ist Decoder.instance, das einen HCursor erhält.

Sie navigieren mit downField und as durch die Felder und geben ein Either zurück.

import io.circe.Decoder

case class User(name: String, age: Int)
implicit val dec: Decoder[User] = Decoder.instance { c =>
  for {
    n <- c.downField("full_name").as[String]
    a <- c.downField("years").as[Int]
  } yield User(n, a)
}

forProductN-Hilfsmethoden

Für einfache Abbildungen ist Decoder.forProduct2 kürzer: Listen Sie die JSON-Schlüssel auf und übergeben Sie den Konstruktor.

Hilfsmethoden gibt es von forProduct1 bis hin zu vielen Argumenten.

import io.circe.Decoder

implicit val dec: Decoder[User] =
  Decoder.forProduct2("full_name", "years")(User.apply)

Ein Encoder von Hand

Bilden Sie den Decoder mit Encoder.instance nach und erstellen Sie aus Ihren Feldern ein Json-Objekt.

Oder verwenden Sie Encoder.forProduct2, um mit einem einzigen Aufruf auf ausgewählte JSON-Schlüssel abzubilden.

import io.circe.Encoder

implicit val enc: Encoder[User] =
  Encoder.forProduct2("full_name", "years")(u =>
    (u.name, u.age))

Vorhandene Codecs transformieren

Nur selten beginnen Sie bei null. map passt die Ausgabe eines Decoders an und contramap die Eingabe eines Encoders.

emap funktioniert wie map, kann aber fehlschlagen und für die Validierung ein Either[String, A] zurückgeben.

import io.circe.Decoder

case class Age(value: Int)
implicit val dec: Decoder[Age] =
  Decoder[Int].emap { i =>
    if (i >= 0) Right(Age(i)) else Left("negative age")
  }

Codecs für Enums

Sealed Traits mit Case-Objekten modellieren Enums. Codieren Sie jeden Fall als Tag-String und decodieren Sie ihn, indem Sie wieder auf diesen String abgleichen.

emap wandelt ein unbekanntes Tag in einen klaren Decodierungsfehler um.

sealed trait Role
case object Admin extends Role
case object Guest extends Role

implicit val dec: Decoder[Role] = Decoder[String].emap {
  case "admin" => Right(Admin)
  case "guest" => Right(Guest)
  case other   => Left(s"unknown role: $other")
}

Das Enum zurückcodieren

Kombinieren Sie den Enum-Decoder mit einem contramap-Encoder, der jeden Fall in sein Tag umwandelt.

Nun wird das Sealed Trait als einfacher String in JSON hin- und zurückcodiert.

import io.circe.Encoder

implicit val enc: Encoder[Role] = Encoder[String].contramap {
  case Admin => "admin"
  case Guest => "guest"
}

Benutzerdefinierter Codec für Datumswerte

Circe bietet im Kernmodul keine integrierten java.time-Codecs, daher sind Datumswerte ein klassischer Fall für einen benutzerdefinierten Codec.

Decodieren und codieren Sie über das ISO-String-Format.

import java.time.LocalDate
import io.circe.{Decoder, Encoder}

implicit val dec: Decoder[LocalDate] =
  Decoder[String].map(LocalDate.parse)
implicit val enc: Encoder[LocalDate] =
  Encoder[String].contramap(_.toString)

Zu einem Codec bündeln

Wenn beide Richtungen vorhanden sind, kombinieren Sie sie mit Codec.from(decoder, encoder) zu einem Codec[A].

So befindet sich nur ein impliziter Wert im Gültigkeitsbereich statt zweier separater Werte.

import io.circe.Codec

implicit val roleCodec: Codec[Role] =
  Codec.from(dec, enc)

Discriminatoren für ADTs

Für Sealed-Hierarchien mit Daten fügt circe-generic-extras ein Discriminator-Feld statt eines umschließenden Objekts hinzu.

Konfigurieren Sie dies einmal und leiten Sie die Codecs für das gesamte ADT ab.

import io.circe.generic.extras._

implicit val cfg: Configuration =
  Configuration.default.withDiscriminator("type")

@ConfiguredJsonCodec sealed trait Shape
@ConfiguredJsonCodec case class Circle(r: Double) extends Shape

Impliziter Gültigkeitsbereich und Priorität

Ein von Hand geschriebener impliziter Codec hat Vorrang vor der Ableitung, solange er im Gültigkeitsbereich liegt. Platzieren Sie ihn im Companion-Objekt, damit er immer gefunden wird.

Vermeiden Sie es, sowohl auto._ als auch eine manuelle Instanz für denselben Typ zu importieren, um Mehrdeutigkeiten zu verhindern.

Kurzer Test

Testen Sie Ihr Verständnis benutzerdefinierter Codecs.

Zusammenfassung

Benutzerdefinierte Codecs verarbeiten JSON, das nicht zu Ihren Typen passt. Erstellen Sie sie mit Decoder.instance oder forProductN oder transformieren Sie vorhandene mit map, contramap und emap.

Enums und Datumswerte sind häufige Anwendungsfälle. Bündeln Sie beide Richtungen mit Codec.from und verwenden Sie Discriminatoren für ADTs.

Häufig gestellte Fragen

Ist die Lektion „Benutzerdefinierte Codecs“ kostenlos?

Ja — der vollständige Text von „Benutzerdefinierte Codecs“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Scala for Backend Engineering & Functional Programming-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Scala for Backend Engineering & Functional Programming-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Benutzerdefinierte Codecs“?

Behandeln Sie schwierige Strukturen. Du übst Scala for Backend Engineering & Functional Programming mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Scala for Backend Engineering & Functional Programming zu starten?

Keine Vorkenntnisse erforderlich. Scala for Backend Engineering & Functional Programming auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.

Wie lange dauert die Lektion „Benutzerdefinierte Codecs“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Scala for Backend Engineering & Functional Programming-Lektion Code schreiben und ausführen?

Ja. Jede Scala for Backend Engineering & Functional Programming-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. JSON parsen
  2. In Case Classes dekodieren
  3. Zu JSON kodieren
  4. Benutzerdefinierte Codecs
← Zurück zu Scala for Backend Engineering & Functional Programming