Last active
March 10, 2020 10:55
-
-
Save nafg/ae190a71c2ede3d51b3ed026e44c8d02 to your computer and use it in GitHub Desktop.
Deriving circe with Magnolia but only as a fallback
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
Note that it isn't important that
default
is in theobject
andgen
is in the trait, sincedefault
is considered more "specific." However, for whatever reason it doesn't work without splitting it into a trait one way or the other.