I am using the semi-automatic decoder derivation that circe provides via deriveDecoder
. There are some custom ADT that I have where I'd like to pass my own decoder for circe to use when it resolves the implicit decoders.
package object json {
implicit val myAdtDecoder: Decoder[MyAdt] = ...
}
This works, although I now need two imports in the file where I call circe's deriveDecoder
.
Is there a way I can set this up so I only need the one import? A sort of "proxy" to circe's deriveDecoder
method that will still use my implicit for MyAdt
?
package object json {
implicit val myAdtDecoder: Decoder[MyAdt] = ...
implicit def deriveDecoder[T]: Decoder[T] = ...
}
Note if I specific T
explicitly here, I'd have no issue solving this problem, but I'd like to keep it generic such that it can work for any T
.
That deriveDecoder
will be automatic here (you don't want to call it yourself), yet you try to import semiauto version.
With the auto approach you can do:
trait ExtendedAuto extends io.circe.generic.AutoDerivation {
implicit val myAdtDecoder: Decoder[MyAdt] = ...
}
package object json extends ExtendedAuto
You have to be careful not to (accidentally) import the same implicits twice, cause then derivation will fail. But if you keep a discipline (e.g. consistendly import only your package object everywhere) then it should be fine.
With semiauto it would be different:
package object json {
implicit val myAdtDecoder: Decoder[MyAdt] = ...
// signatures copy-pasted from io.circe.generic.semiauto
import io.circe.generic.semiauto
final def deriveDecoder[A](implicit decode: Lazy[DerivedDecoder[A]]): Decoder[A] = semiauto.deriveDecoder[A]
final def deriveEncoder[A](implicit encode: Lazy[DerivedObjectEncoder[A]]): ObjectEncoder[A] = semiauto.deriveEncoder[A]
}
But if your are using semiauto, you are probably putting stuff into companion objects to avoid multiple derivations of the same codec. In this case you can consider using something like @JsonCodec.