I'm trying to convert a case class that has a Enumeration as a argument
import io.circe._, io.circe.generic.auto._, io.circe.jawn._, io.circe.syntax._
object WeekDay extends Enumeration {
val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
case class test1(day: WeekDay.Value)
case class test2(day: String)
While test2("Mon").asJson works as expected:
{
"day" : "Mon"
}
But: test1(WeekDay.Mon).asJson results in:
:27: error: could not find implicit value for parameter encoder: io.circe.Encoder[test]
test(WeekDay.Mon).asJson
Is there a way to work around this or is this a bug?
I'm not seeing anywhere in the project where basic scala Enumerations have a provided Encoder/Decoder instance. However, following how the json4s handled this I came up with the following
class EnumTranscoder[E <: Enumeration](enum: E) extends Decoder[E#Value] with Encoder[E#Value] {
override def apply(c: HCursor): Result[E#Value] = Decoder.decodeString.map(enum.withName).apply(c)
override def apply(a: E#Value): Json = Encoder.encodeString.apply(a.toString)
}
This isn't exactly a bug, but it is at least arguably a missing feature. There are lots of reasons not to use Scala's Enumeration, and circe (and Argonaut before it) has never provided built-in support for them.
If there's demand, though, I definitely think we could consider a PR adding something like the instances in @dhensche's comment to Encoder and Decoder.
There are certainly reasons, but sometimes you don't have control over these things, so an integrated enumeration encoder would definitely be very useful.
The class-based version above didn't work for me, but this one works (similarly used in Play JSON):
def enumDecoder[E <: Enumeration](enum: E) = new Decoder[E#Value] {
override def apply(c: HCursor): Result[E#Value] = Decoder.decodeString.map(str => enum.withName(str)).apply(c)
}
Where would this have to go in Circe, directly into Encoder and Decoder? (I'm pretty new to it.) I could create a PR.
Yes, we'd want them to be in the companion objects so that they get made available without additional imports. Thanks, @mariussoutier!
Most helpful comment
I'm not seeing anywhere in the project where basic scala Enumerations have a provided Encoder/Decoder instance. However, following how the json4s handled this I came up with the following