2

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)
pme
  • 14,156
  • 3
  • 52
  • 95
  • The Play `Format` combinator 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`. Therefore you'd need to manually write your own `Reads` and `Writes` combinators 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. – Lasf Sep 19 '18 at 17:17
  • @Lasf - thanks - can you put this in an answer - so I can accept it. – pme Sep 20 '18 at 06:14
  • Sure, done. Thanks – Lasf Sep 20 '18 at 14:59

1 Answers1

3

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)
Lasf
  • 2,536
  • 1
  • 16
  • 35