簡単な答え:PlayEnumerationUtilsのようなものを使用してください。
長い答えですが、列挙型に読み取りを入れる代わりに、列挙型の再利用可能な読み取りを作成できます。
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")
}
}
}
次に、何かを列挙型に解析する場合は、スコープ内の特定の列挙型の暗黙的な読み取りを作成します。
import some.thing.EnumUtils
implicit val myEnumReads: Reads[EnumA.Value] = EnumUtils.enumReads(EnumA)
val myValue: EnumA.Value = someJsonObject.as[EnumA.Value]
また
val myValue: EnumA.Value = someJsonObject.asOpt[EnumA.Value].getOrElse(sys.error("Oh noes! Invalid value!"))
(Scalaでnullを使用するのは悪い形式と見なされます。)
JsValuesとして列挙型を記述する方が簡単です。
object EnumUtils {
...
implicit def enumWrites[E <: Enumeration]: Writes[E#Value] = new Writes[E#Value] {
def writes(v: E#Value): JsValue = JsString(v.toString)
}
}
次に、列挙型を書き込もうとする前に、それをスコープにインポートします(または、toJson
関数に明示的に渡します。
import EnumUtils.enumWrites
val myEnumJson: JsValue = Json.toJson(EnumA.VAL1)
同様に、読み取りと書き込みの両方を組み合わせたFormatオブジェクトを作成する関数を作成できます。
object EnumUtils {
....
implicit def enumFormat[E <: Enumeration](enum: E): Format[E#Value] = {
Format(EnumReader.enumReads(enum), EnumWriter.enumWrites)
}
}