How to write Reads[T] and Writes[T] in scala Enumeration (play framework 2.1) How to write Reads[T] and Writes[T] in scala Enumeration (play framework 2.1) json json

How to write Reads[T] and Writes[T] in scala Enumeration (play framework 2.1)


Short answer: use something like Play Enumeration Utils.

Long answer, instead of putting a Reads in your enum, you can create a re-useable Reads for Enumeration types:

object EnumA extends Enumeration {  type EnumA = Value  val VAL1, VAL2, VAL3 = Value}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")    }  }}

Then when you want to parse something to an enum, create an implicit Reads for your specific Enum type in scope:

import some.thing.EnumUtilsimplicit val myEnumReads: Reads[EnumA.Value] = EnumUtils.enumReads(EnumA)val myValue: EnumA.Value = someJsonObject.as[EnumA.Value]

or

val myValue: EnumA.Value = someJsonObject.asOpt[EnumA.Value].getOrElse(sys.error("Oh noes! Invalid value!"))

(It's considered bad form to use null in Scala.)

Writing enums as JsValues is simpler:

object EnumUtils {  ...  implicit def enumWrites[E <: Enumeration]: Writes[E#Value] = new Writes[E#Value] {    def writes(v: E#Value): JsValue = JsString(v.toString)  }}

Then just import that into scope before you attempt to write an enum (or pass it explicitly to the toJson function:

import EnumUtils.enumWritesval myEnumJson: JsValue = Json.toJson(EnumA.VAL1)

You can similarly make a function to create a Format object combining both Reads and Writes:

object EnumUtils {  ....  implicit def enumFormat[E <: Enumeration](enum: E): Format[E#Value] = {    Format(EnumReader.enumReads(enum), EnumWriter.enumWrites)  }}