scalaenumsdecodingscala-3circe

How to provide a generic Circe Decoder for a Scala 3 Enum Values?


In my model I have a subset of Enum Values (using refined types). So I need to provide Decoders for these Enum Values.

I have now the following version that works (I simplified the example with only one enum value):

import io.circe.*

inline def deriveEnumValueDecoder[A](inline prototype: A): Decoder[A] =
  Decoder.decodeString.emap: str =>
    if str == prototype.toString
    then Right(prototype)
    else Left(s"Invalid value: $str")


val json = Json.obj("processStatus" -> Json.fromString("OK"))
val jsonEnum = Json.fromString("OK")

println("MyClass: " + json.as[MyClass])
println("MyEnum: " + jsonEnum.as[MyEnum.OK.type])


case class MyClass(processStatus: MyEnum.OK.type) 

enum MyEnum:
  case OK, NOK

given Decoder[MyClass] = Decoder.derived
given Decoder[MyEnum.OK.type] = deriveEnumValueDecoder(MyEnum.OK)

See Scastie: https://scastie.scala-lang.org/pme123/ntclYMfzQK2U6KP1wv9fIw/2

I was wondering if there is a way to get rid of providing a 'prototype', so I can call it like:

given Decoder[MyEnum.OK.type] = deriveEnumValueDecoder

Solution

  • With the comment of Mateusz Kubuszok:

    inline def deriveEnumValueDecoder[A]: Decoder[A] =
        Decoder.decodeString.emap: str =>
          if str == valueOf[A].toString
          then Right(valueOf[A])
          else Left(s"Invalid value: $str - expected: ${valueOf[A]}")
    
    given Decoder[MyEnum.OK.type] = deriveEnumValueDecoder