public
Last active

Example Play JSON Enum reading/writing

  • Download Gist
gistfile1.scala
Scala
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
package enumtest
 
 
import play.api.libs.json._
 
 
object EnumUtils {
def enumReads[E <: Enumeration](enum: E): Reads[E#Value] = new Reads[E#Value] {
def reads(json: JsValue): JsResult[E#Value] = json match {
case JsString(s) => {
try {
JsSuccess(enum.withName(s))
} catch {
case _: NoSuchElementException => JsError(s"Enumeration expected of type: '${enum.getClass}', but it does not appear to contain the value: '$s'")
}
}
case _ => JsError("String value expected")
}
}
 
implicit def enumWrites[E <: Enumeration]: Writes[E#Value] = new Writes[E#Value] {
def writes(v: E#Value): JsValue = JsString(v.toString)
}
 
implicit def enumFormat[E <: Enumeration](enum: E): Format[E#Value] = {
Format(EnumReader.enumReads(enum), EnumWriter.enumWrites)
}
}
 
 
// Now let's test it
 
object EnumTest {
 
object EnumA extends Enumeration {
type EnumA = Value
val VAL1, VAL2, VAL3 = Value
}
 
implicit val enumAFormat = EnumUtils.enumFormat(EnumA)
val myEnumJson: JsValue = Json.toJson(EnumA.VAL1)
val myValue: EnumA.Value = myEnumJson.asOpt[EnumA.Value].getOrElse(sys.error("Oh noes! Invalid value!"))
 
def ok = EnumA.VAL1 == myValue
}

Hi

line 26: EnumReader is not defined. I removed it and the error was gone

when i use it like so:

object Status extends Enumeration {
    type Status = Value
    val Enabled, Disabled = Value
}

case class Product(id: Option[Long], ean: Long, name: String, description: String, status: Status = Status.Enabled)

implicit val productWrites = (
        (__ \ "id").write[Option[Long]] ~
        (__ \ "ean").write[Long] ~ 
        (__ \ "name").write[String] ~
        (__ \ "description").write[String] ~
        (__ \ "status").write[Status]
    )(unlift(Product.unapply))

    implicit val productReads = (
        (__ \ "id").readNullable[Long] ~
        (__ \ "ean").read[Long] ~ 
        (__ \ "name").read[String] ~
        (__ \ "description").read[String] ~
        (__ \ "status").read[Status]  
    )(Product)

the (__ \ "status").write[Status] works ok, but (__ \ "status").read[Status] gives an error "Description Resource Path Location Type
No Json formatter found for type models.Status.Status. Try to implement an implicit Format for this type"

why doesn't it work for "read"?

Thank you

In line 26 just change the EnumReader to EnumUtils. After that you should be able to write something like this:

implicit val enumTypeFormat = EnumUtils.enumFormat(EnumClass)

At least for me it works.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.