2013-03-18 12 views
24

Sono un po 'perso con la nuova funzione di ScalaJson in Play Framework 2.1. Mi piacerebbe scrivere Leggi e Scrive nella mia enumerazione.Come scrivere Leggi [T] e Scrive [T] in scala Enumeration (play framework 2.1)

Ecco il mio codice:

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 
    } 
}} 

Qualche idea?

Grazie.

risposta

41

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) 
    } 
} 
+0

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

+1

@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

+0

Grazie mille. – smk

Problemi correlati