Skip to content

Instantly share code, notes, and snippets.

@agile-jordi
Last active April 22, 2016 05:06
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agile-jordi/6809100 to your computer and use it in GitHub Desktop.
Save agile-jordi/6809100 to your computer and use it in GitHub Desktop.
An object with functions the create Reads, Writes or Formats for Enums.
// With an enumeration like...
// object Color extends Enumeration{...}
// Create a format (or reads or writes) like this:
// val fmt = EnumJson.enumFormat(Color);
// The implementation
object EnumJson {
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 contain '$s'")
}
}
case _ => JsError("String value expected")
}
}
implicit def enumWrites[E <: Enumeration]: Writes[E#Value] = new Writes[E#Value] {
def writes(v: E#Value): JsValue = JsString(v.toString)
}
implicit def enumFormat[E <: Enumeration](enum: E): Format[E#Value] = {
Format(enumReads(enum), enumWrites)
}
}
@blancosj
Copy link

or

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

Sample usage

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment