-
add
import io.circe.generic.auto._
where you use the auto-derived JSON encoders and decoders (don't import at file-level, but instead on object/class-level!)-
e.g. in a file
Datastructures.scala
you declaresealed case Data(x: Int)
and inUsage.scala
you haveimport io.circe.Json // needed? // for .asJson methods to be "added" to classes for which implicit encoders exist import io.circe.syntax._ object Usage { // here we want to make an implicit encoder exist by the auto derive magic of circe: // important: this import must happen inside the Usage object, not above!!! import io.circe.generic.auto._ val d: Data = Data(42) def main(args: Array[String]): Unit = { println(d.asJson) } }
-
-
Have all your case classes for which you would like auto codecs to be derived
sealed
! -
Do not import
io.circe.generic.auto._
andio.circe.generic.extras.auto._
at the same time. For me that led to implicit codecs not being created somehow. -
Beware of important import statement being marked as unused and then removed (upon clean-up) by IntelliJ. Example from my code:
I recommend annotating with heavy comments.
-
Debugging:
If you get one of the errors
could not find Lazy implicit value of type io.circe.generic.decoding.DerivedEncoder[A]
orcould not find Lazy implicit value of type io.circe.generic.encoding.DerivedDecoder[A]
,
this means the implicit encoder/decoder for A
cannot be found. If you use (or at least intended to use) the auto derive magic of circe via io.circe.generic.auto._
(or io.circe.generic.extras.auto._
), then most probably the auto derivation for the respective encoder/decoder did not kick in. Possible reasons are:
- your case classes are not `sealed`
- your case classes got parameters for which auto codecs cannot be derived, e.g. `sealed case class Data(x: Any)`
- you're importing `io.circe.generic.auto._` and `io.circe.generic.extras.auto._` at the same time.
- you imported one of the above imports at the wrong scope. They introduce implicit values, hence they need to be imported in a scope that a) allows declaration of implicit variables (e.g. inside an `object ... { ... }` or class, *not* file scope) and b) is a parent scope of the scope where you want to access the auto-derived codecs.
Manual Pinpointing: (due to this StackOverflow comment) If the tips above don't help you, you can try pinpointing the problem as follows: say you have sealed case class Data(x: Any)
and sealed case class Container(d: Data)
and you want to auto-derive a codec for Container
:
import io.circe.{Encoder, Decoder}
sealed case class Data(x: Any)
sealed case class Container(label: String, d: Data)
object DebuggingTips {
import io.circe.generic.auto._
// this line will *not* compile
// the error will be "could not find Lazy implicit value of type io.circe.generic.decoding.DerivedEncoder[Container]"
val containerEnc = io.circe.Encoder[Container]
}
Then manually look at the parameter types of Container
and see if for them, a codec can be automatically derived:
import io.circe.{Encoder, Decoder}
sealed case class Data(x: Any)
sealed case class Container(label: String, d: Data)
object DebuggingTips {
import io.circe.generic.auto._
// no error here => label parameter is apparently fine!
val labelEnc = io.circe.Encoder[String]
// error here! Namely "could not find Lazy implicit value of type io.circe.generic.decoding.DerivedEncoder[Data]"
// => aha!
// the reason why a codec for Container cannot be auto-derived is most probably
// due to the reason why a codec for Data cannot be auto-derived
val dataEnc = io.circe.Encoder[Data]
}