Play 2.1(scala) - 如何为scala枚举案例类编写Format [T]

时间:2013-05-23 16:35:19

标签: json scala playframework playframework-2.1

这个问题与以下两个问题有关。

我们想在我们的play 2.1应用程序中使用模型中的枚举,所以我们发现了以下问题 How to write Reads[T] and Writes[T] in scala Enumeration (play framework 2.1)

然后提到在scala中使用case类比scala枚举更好。所以我们发现了以下问题

Case objects vs Enumerations in Scala

我们如何编写上面建议的case类枚举的json格式?例如,案例类枚举就像

trait Enum[A] {
  trait Value { self: A => }
  val values: List[A]
}

sealed trait Currency extends Currency.Value
object Currency extends Enum[Currency] {
  case object EUR extends Currency
  case object GBP extends Currency
  val values = List(EUR, GBP)
}

我们是Play / scala的新手,特别是它的功能性JSON api。我试着写谢谢

2 个答案:

答案 0 :(得分:2)

我为此编写了一个实现,这是我写的关于它的博客文章。

http://kailuowang.blogspot.com/2013/05/case-class-enumeration-in-play-21-and.html

答案 1 :(得分:-1)

其他实施

object EnumFormat {
  implicit def jsonReads[A](enum: Enumeration): Reads[A] = new Reads[A] {
    def reads(json: JsValue): JsResult[A] = json match {
      case JsString(s) => {
        try {
          JsSuccess(enum.withName(s).asInstanceOf[A])
        } catch {
          case _: NoSuchElementException =>
            JsError(s"Enumeration expected of type: '${enum.getClass}', but it does not contain '$s'")
        }
      }
      case _ => JsError("String value expected")
    }
  }
  implicit def jsonWrites[A]: Writes[A] = new Writes[A] {
    def writes(v: A): JsValue = JsString(v.toString)
  }
  implicit def jsonFormat[A](enum: Enumeration): Format[A] = {
    Format(jsonReads(enum), jsonWrites)
  }
}

object DeviceStatus extends Enumeration {

  val UNKNOWN = DeviceStatusType(0x0)
  val REGISTERED = DeviceStatusType(0x1)
  val NO_REGISTERED = DeviceStatusType(0x1000)

  case class DeviceStatusType(code: Int) extends Val(code) {

    import play.api.libs.json._
    import play.api.libs.functional.syntax._

    implicit def valueTo(v: Value): DeviceStatusType = v.asInstanceOf[DeviceStatusType]
  }

  implicit val jsonFormat: Format[DeviceStatus.DeviceStatusType] = EnumFormat.jsonFormat(DeviceStatus)
}