I'm a little bit lost with the new ScalaJson Feature in Play Framework 2.1. I would like to write Reads and Writes in my Enumeration.
Here is my code :
object EnumA extends Enumeration { type EnumA = Value val VAL1, VAL2, VAL3 = Value def parse(str:String) : EnumA = { str.toUpperCase() match { case "VAL1" => VAL1 case "VAL2" => VAL2 case "VAL3" => VAL3 case _ => null } }}
Any idea ?
Thanks.
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.EnumUtils implicit 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.enumWrites val 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) } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With