Deriving circe with Magnolia but only as a fallback
| import scala.language.experimental.macros | |
| import scala.reflect.ClassTag | |
| import io.circe.{Decoder, Encoder, Json} | |
| import magnolia._ | |
| class ParamEncoder[T](val underlying: Encoder[T]) extends AnyVal | |
| trait ParamEncoderLowPriority { | |
| type Typeclass[T] = ParamEncoder[T] | |
| def combine[T](caseClass: CaseClass[Typeclass, T]): Typeclass[T] = | |
| new Typeclass(Encoder.instance { value => | |
| Json.obj(caseClass.parameters.map(p => p.label -> p.typeclass.underlying(p.dereference(value))): _*) | |
| }) | |
| implicit def gen[T]: Typeclass[T] = macro Magnolia.gen[T] | |
| } | |
| object ParamEncoder extends ParamEncoderLowPriority { | |
| implicit def default[A](implicit A: Encoder[A]): Typeclass[A] = new Typeclass(A) | |
| } | |
| class ParamDecoder[T](val underlying: Decoder[T]) extends AnyVal | |
| trait ParamDecoderLowPriority { | |
| type Typeclass[T] = ParamDecoder[T] | |
| def combine[T](caseClass: CaseClass[Typeclass, T]): Typeclass[T] = | |
| new Typeclass(Decoder.instance { cursor => | |
| caseClass.constructEither(param => cursor.get(param.label)(param.typeclass.underlying)).left.map(_.head) | |
| }) | |
| implicit def gen[T]: Typeclass[T] = macro Magnolia.gen[T] | |
| } | |
| object ParamDecoder extends ParamDecoderLowPriority { | |
| implicit def default[A](implicit A: Decoder[A]): Typeclass[A] = new Typeclass(A) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Note that it isn't important that
defaultis in theobjectandgenis in the trait, sincedefaultis considered more "specific." However, for whatever reason it doesn't work without splitting it into a trait one way or the other.