Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Circe and Scala's Enumeration type

Tags:

json

scala

circe

I'm trying to wrap my head around Circe.

So, here's the model I've been given:

object Gender extends Enumeration {
     type Gender = Value
     val Male, Female, Unisex, Unknown = Value
}

case class Product(id: String, gender: Gender.Value)

I want to

a) encode the following example as JSON

        val product = Product(id = "1234", gender = Gender.Female)

b) map the resulting JSON back onto the Product case class.


My own attempt didn't get me far:

  object JsonProtocol {
      implicit val productDecoder: Decoder[Product] = deriveDecoder
      implicit val productEncoder: Encoder[Product] = deriveEncoder
  }

result is a compile time error

   Error:(52, 49) could not find Lazy implicit value of type io.circe.generic.decoding.DerivedDecoder[A]
   implicit val productDecoder: Decoder[Product] = deriveDecoder
                                            ^

I've no idea why this exception is thrown and what the solution could look like. Maybe it's the usage of the Enumeration type?

like image 939
simou Avatar asked Feb 06 '17 13:02

simou


2 Answers

The accepted answer is deprecated (circe 0.12.0).

Circe provides now these functions:

Decoder.decodeEnumeration[E <: Enumeration](enum: E)
Encoder.encodeEnumeration[E <: Enumeration](enum: E)

With the example:

implicit val genderDecoder: Decoder[Gender.Value] = Decoder.decodeEnumeration(Gender)
implicit val genderEncoder: Encoder[Gender.Value] = Encoder.encodeEnumeration(Gender)
like image 161
pme Avatar answered Oct 24 '22 08:10

pme


Try defining your own encoders and decoders for the enum using:

Decoder.enumDecoder[E <: Enumeration](enum: E)
Encoder.enumEncoder[E <: Enumeration](enum: E)

something like:

object JsonProtocol {
  implicit val genderDecoder: Decoder[Gender.Value] = Decoder.enumDecoder(Gender)
  implicit val genderEncoder: Encoder[Gender.Value] = Encoder.enumEncoder(Gender)
  implicit val productDecoder: Decoder[Product] = deriveDecoder
  implicit val productEncoder: Encoder[Product] = deriveEncoder
}

These are needed because the automatic/semiautomatic derivers only work for hierarchies of sealed traits and case classes as far as I know. The reason you see that error is because the derived codecs for Product will implicitly require encoders/decoders for the types of each of it's parameters. An encoder/decoder for String is a standard part of Circe, but you'll probably need to create ones for your own enumerations.

like image 15
Howy Perrin Avatar answered Oct 24 '22 08:10

Howy Perrin