Skip to content

Instantly share code, notes, and snippets.

@cyppan
Created February 3, 2015 12:52
Show Gist options
  • Save cyppan/edcda7e67c1551e0122c to your computer and use it in GitHub Desktop.
Save cyppan/edcda7e67c1551e0122c to your computer and use it in GitHub Desktop.
Scala Enumeration alternative
import play.api.libs.json.{JsValue => PJsValue, JsString => PJsString, _}
import spray.json
import spray.json.{DeserializationException, JsString, JsValue, JsonFormat}
/**
* Enum alternative with Json marshallers for free (Play and Spray)
*
* credit: https://gist.github.com/atamborrino/1d992ebb942cd5518ca2
*
* Use:
* sealed trait Dsp
* object Dsp extends ADTEnum[Dsp] {
* case object AppNexus extends Dsp
* case object MediaMath extends Dsp
* val list = Seq(AppNexus, MediaMath)
* }
*
* def foo(dsp: Dsp) = dsp match {
* case Dsp.AppNexus => "foo"
* case Dsp.MediaMath => "bar"
* }
* @tparam A
*/
trait ADTEnum[A] {
val list: Seq[A]
def withName(name: String): Option[A] = {
list.find(_.toString.toLowerCase == name.toLowerCase)
}
implicit val sprayJsonReads: JsonFormat[A] = new JsonFormat[A] {
def read(json: JsValue): A = json match {
case JsString(raw) =>
withName(raw)
.getOrElse(throw new DeserializationException("error.ADTEnumUnknown"))
case _ => throw new DeserializationException("error.ADTEnumMustBeAString")
}
def write(obj: A): JsValue = JsString(obj.toString)
}
implicit val playJsonFormat: Format[A] = new Format[A] {
override def writes(o: A): PJsValue =
PJsString(o.toString)
override def reads(json: PJsValue): JsResult[A] =
json match {
case PJsString(raw) =>
withName(raw) match {
case Some(a) => JsSuccess(a)
case None => JsError(__, "error.ADTEnumUnknown")
}
case _ => JsError(__, "error.ADTEnumMustBeAString")
}
}
}
@cyppan
Copy link
Author

cyppan commented Feb 3, 2015

Choose your preferred json library over spray-json or play-json here.
Based on the atamborrino original Gist but without the dependency to jto / validation.

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