0Pricing
Scala for Backend Engineering & Functional Programming · Aula

Codecs personalizados

Lide com estruturas complexas.

Codecs personalizados é uma aula grátis de Scala for Backend Engineering & Functional Programming no CoddyKit. Esta é a aula 4 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.

Quando você precisa de codificadores personalizados

A derivação cobre o caso comum, mas às vezes o JSON não espelha sua classe de caso: nomes de campos legados, enumeradores codificados ou formatos como marcas de tempo.

Nesse caso, você escreve manualmente um Decoder, um Encoder ou ambos.

Um decodificador a partir de um cursor

A forma mais explícita de criar um decodificador é Decoder.instance, que recebe um HCursor.

Você navega pelos campos com downField e as, retornando um Either.

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)
}

Auxiliares forProductN

Para mapeamentos diretos, Decoder.forProduct2 é mais conciso: liste as chaves JSON e passe o construtor.

Há auxiliares desde forProduct1 até várias outras quantidades de argumentos.

import io.circe.Decoder

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

Um codificador manual

Replique o decodificador com Encoder.instance, construindo um objeto Json a partir dos seus campos.

Ou use Encoder.forProduct2 para mapeá-los de volta para as chaves JSON escolhidas com uma única chamada.

import io.circe.Encoder

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

Transformando codificadores existentes

Raramente se começa do zero. map adapta a saída de um decodificador, e contramap adapta a entrada de um codificador.

emap é semelhante a map, mas pode falhar, retornando Either[String, A] para validação.

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 para enums

Traços selados com objetos de caso modelam enums. Codifique cada um como uma cadeia de caracteres de identificação e decodifique comparando novamente com essa cadeia.

emap transforma uma identificação desconhecida em uma falha de decodificação clara.

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")
}

Codificando o enum de volta

Associe o decodificador do enum a um codificador contramap que converta cada caso na sua identificação.

Agora o traço selado faz conversão de ida e volta como uma simples cadeia de caracteres em JSON.

import io.circe.Encoder

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

Codec personalizado para datas

O Circe não possui codecs integrados para java.time no módulo principal, portanto datas são um caso clássico de codec personalizado.

Decodifique e codifique usando o formato de cadeia de caracteres ISO.

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)

Agrupando em um codec

Quando você tem as duas direções, combine-as em um único Codec[A] com Codec.from(decoder, encoder).

Isso mantém um único implícito no escopo, em vez de dois separados.

import io.circe.Codec

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

Discriminadores para ADTs

Para hierarquias seladas com dados, circe-generic-extras adiciona um campo discriminador em vez de um objeto wrapper.

Configure-o uma vez e derive codecs para todo o ADT.

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

Escopo e prioridade de implícitos

Um codec implícito escrito manualmente tem precedência sobre a derivação, desde que esteja no escopo. Coloque-o no objeto companheiro para que seja sempre encontrado.

Evite importar tanto auto._ quanto uma instância manual para o mesmo tipo, a fim de evitar ambiguidades.

Verificação rápida

Teste sua compreensão sobre codecs personalizados.

Recapitulação

Codecs personalizados lidam com JSON que não corresponde aos seus tipos. Crie-os com Decoder.instance, forProductN ou transforme os existentes usando map, contramap e emap.

Enums e datas são casos comuns; agrupe as direções com Codec.from e use discriminadores para ADTs.

Perguntas Frequentes

A aula “Codecs personalizados” é grátis?

Sim — o texto completo de “Codecs personalizados” é 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 “Codecs personalizados”?

Lide com estruturas complexas. 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 4 de 4.

Quanto tempo leva a aula “Codecs personalizados”?

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.

Todas as aulas deste curso

  1. Analisando JSON
  2. Decodificando em classes de caso
  3. Codificando para JSON
  4. Codecs personalizados
← Voltar para Scala for Backend Engineering & Functional Programming