Risposta breve: utilizzare qualcosa come Play Enumeration Utils.
Risposta lunga, invece di mettere un Legge in vostra enum, è possibile creare una ri-utilizzabile Legge per i tipi di enumerazione:
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")
}
}
}
Poi, quando si vuole analizzare qualcosa per un enum, creare un implicita Legge per il vostro tipo specifico Enum nel campo di applicazione:
import some.thing.EnumUtils
implicit val myEnumReads: Reads[EnumA.Value] = EnumUtils.enumReads(EnumA)
val myValue: EnumA.Value = someJsonObject.as[EnumA.Value]
o
val myValue: EnumA.Value = someJsonObject.asOpt[EnumA.Value].getOrElse(sys.error("Oh noes! Invalid value!"))
(. E 'considerato di cattivo gusto di utilizzare null a Scala)
scrittura enumerazioni come JsValues è più semplice:
object EnumUtils {
...
implicit def enumWrites[E <: Enumeration]: Writes[E#Value] = new Writes[E#Value] {
def writes(v: E#Value): JsValue = JsString(v.toString)
}
}
Poi basta importare che in ambito prima di tentare di scrivere un enum (o passarlo in modo esplicito alla funzione toJson
:
import EnumUtils.enumWrites
val myEnumJson: JsValue = Json.toJson(EnumA.VAL1)
È possibile allo stesso modo fare una funzione per creare un oggetto formato che combina sia legge e scrive:
object EnumUtils {
....
implicit def enumFormat[E <: Enumeration](enum: E): Format[E#Value] = {
Format(EnumReader.enumReads(enum), EnumWriter.enumWrites)
}
}
Quando provo il codice nel repl ricevo il seguente errore myEnumReads val implicite: Legge [Enûma # Valore] = EnumUtils.enumReads (Enûma) errore: non trovato: Tipo di Enûma implicite myEnumReads val: Legge [Enûma #Value] = EnumUtils.enumReads (EnumA) ^ – smk
@smk: Il contesto OPs era implicito nel codice che ho postato. L'ho aggiornato per essere incluso ora. Ecco la piena [cosa come un gist] (https://gist.github.com/mikesname/5237809) – Mikesname
Grazie mille. – smk