scalaplay-jsonenumeratum

Using an Enumeratum Enum in a Map does not work


I have an Enumeration created with enumeratum:

sealed trait Language extends EnumEntry

object Language
  extends Enum[Language]
    with PlayInsensitiveJsonEnum[Language] {

  val values: IndexedSeq[Language] = findValues

  case object DE extends Language
  ...
}

If I use it in a Map it throws:

No instance of play.api.libs.json.Format is available for scala.collection.immutable.Map[finnova.bpf.api.entity.Language, java.lang.String] in the implicit scope (Hint: if declared in the same file, make sure it's declared before)

Here is the definition:

case class I18nEntry(values: Map[Language, String])

object I18nEntry {
  implicit val jsonFormat: Format[I18nEntry] = Json.format[I18nEntry]
}

This here works:

case class I18nEntry(values: Map[String, String], language: Language)

Solution

  • The Play Format converter for a Map will only be implicitly provided if your Map key is a String, as JSON object keys must be strings. It doesn't realize that Language is eventually a String (or, rather, a JsString). Therefore you'd need to manually write your own Reads and Writes converters for Map[Language, String], or alternatively map Language to a String key such as you have values: Map[String, String] as you've done above. For what it's worth, the first solution would take roughly this structure:

    val langMapReads: Reads[Map[Language, String]] = ???
    val langMapWrites: Writes[Map[Language, String]] = ???
    implicit val langMapFormat: Format[Map[Language, String]] = Format(langMapReads, langMapWrites)