如何在scala枚举中编写Read [T]和Writes [T](播放框架2.1)

时间:2013-03-18 23:05:52

标签: json scala playframework-2.1

我对Play Framework 2.1中新的ScalaJson功能有点失落。 我想在我的枚举中写入读写。

这是我的代码:

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

有什么想法吗?

感谢。

1 个答案:

答案 0 :(得分:41)

简短回答:使用类似Play Enumeration Utils的内容。

答案很长,你可以为枚举类型创建一个可重复使用的Reads:

,而不是在枚举中读取
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)

您可以类似地创建一个函数来创建一个结合了Read和Writes的Format对象:

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