Skip to content

Instantly share code, notes, and snippets.

@atamborrino
Last active August 29, 2015 14:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atamborrino/1d992ebb942cd5518ca2 to your computer and use it in GitHub Desktop.
Save atamborrino/1d992ebb942cd5518ca2 to your computer and use it in GitHub Desktop.
// Enum type based on Sum types (OR)
trait ADTEnum[A] {
import play.api.data.mapping.json.Writes._
import play.api.data.mapping.json.Rules._
val list: Seq[A]
def withName(name: String): Option[A] = {
list.find(_.toString.toLowerCase == name.toLowerCase)
}
implicit val jsonReads: Rule[JsValue, A] = Rule.fromMapping {
case JsString(str) =>
withName(str) match {
case Some(name) => Success(name)
case None => Failure(Seq(ValidationError(s"error.unknownADTEnum")))
}
case _ => Failure(Seq(ValidationError(s"error.ADTEnumMustBeAString")))
}
implicit val jsonWrites: Write[A, JsString] = Write(a => JsString(a.toString))
}
@atamborrino
Copy link
Author

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

@atamborrino
Copy link
Author

Advantages over Enumeration:

  • Better syntax: type is Dsp, a value is Dsp.AppNexus (no more "Enumeration.Value")
  • Safe pattern matching with compiler warning if a case has been forgotten
  • Automatic jsonWrites and jsonReads

@vil1
Copy link

vil1 commented Jan 24, 2015

Nice !

@cyppan
Copy link

cyppan commented Feb 3, 2015

cool thanks, here is an implementation with Spray and Play Json marshalling (dependencies: play-json, spray-json) => https://gist.github.com/cyppan/edcda7e67c1551e0122c

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