Skip to content

Instantly share code, notes, and snippets.

@nafg
Last active March 10, 2020 10:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nafg/ae190a71c2ede3d51b3ed026e44c8d02 to your computer and use it in GitHub Desktop.
Save nafg/ae190a71c2ede3d51b3ed026e44c8d02 to your computer and use it in GitHub Desktop.
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)
}
@nafg
Copy link
Author

nafg commented Mar 8, 2020

Note that it isn't important that default is in the object and gen is in the trait, since default is considered more "specific." However, for whatever reason it doesn't work without splitting it into a trait one way or the other.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment