Semi-automatic Derivation

Sometimes it’s convenient to have an Encoder or Decoder defined in your code, and semi-automatic derivation can help. You’d write:

import io.circe._, io.circe.generic.semiauto._

case class Foo(a: Int, b: String, c: Boolean)

implicit val fooDecoder: Decoder[Foo] = deriveDecoder[Foo]
implicit val fooEncoder: Encoder[Foo] = deriveEncoder[Foo]

Or simply:

implicit val fooDecoder: Decoder[Foo] = deriveDecoder
implicit val fooEncoder: Encoder[Foo] = deriveEncoder

@JsonCodec

The circe-generic project includes a @JsonCodec annotation that simplifies the use of semi-automatic generic derivation:

import io.circe.generic.JsonCodec, io.circe.syntax._
// import io.circe.generic.JsonCodec
// import io.circe.syntax._

@JsonCodec case class Bar(i: Int, s: String)
// defined class Bar
// defined object Bar

Bar(13, "Qux").asJson
// res0: io.circe.Json =
// {
//   "i" : 13,
//   "s" : "Qux"
// }

This works with both case classes and sealed trait hierarchies.

NOTE: You will need the Macro Paradise plugin to use annotation macros like @JsonCodec

forProductN helper methods

It’s also possible to construct encoders and decoders for case class-like types in a relatively boilerplate-free way without generic derivation:

import io.circe.{ Decoder, Encoder }
// import io.circe.{Decoder, Encoder}

case class User(id: Long, firstName: String, lastName: String)
// defined class User

implicit val decodeUser: Decoder[User] =
  Decoder.forProduct3("id", "first_name", "last_name")(User.apply)
// decodeUser: io.circe.Decoder[User] = io.circe.ProductDecoders$$anon$3@1d97297d

implicit val encodeUser: Encoder[User] =
  Encoder.forProduct3("id", "first_name", "last_name")(u =>
    (u.id, u.firstName, u.lastName)
  )
// encodeUser: io.circe.Encoder[User] = io.circe.ProductEncoders$$anon$3@72852704

It’s not as clean or as maintainable as generic derivation, but it’s less magical, it requires nothing but circe-core, and if you need a custom name mapping it’s currently the best solution (although 0.6.0 introduces experimental configurable generic derivation in the circe-generic-extras module).