Skip to content

Instantly share code, notes, and snippets.

@jserranohidalgo
Last active September 29, 2017 18:10
Show Gist options
  • Save jserranohidalgo/0c5c9998f581f26c1150 to your computer and use it in GitHub Desktop.
Save jserranohidalgo/0c5c9998f581f26c1150 to your computer and use it in GitHub Desktop.
Exploit tagged types to add constraints on standard values, with custom Json deserializers
import play.api.libs.json._
import play.api.data.validation.ValidationError
object Test{
type Tagged[U] = { type Tag = U }
trait NonEmpty
type NonEmptyString = String with Tagged[NonEmpty]
case class Foo(str1: NonEmptyString, str2: String)
implicit val NonEmptyStringReads = new Reads[NonEmptyString]{
def reads(json: JsValue): JsResult[NonEmptyString] =
json.validate[String]
.filterNot(ValidationError("String is empty!"))(_.isEmpty)
.map(_.asInstanceOf[NonEmptyString])
}
implicit val FooReads = Json.reads[Foo]
assert(Json.obj("str1" -> "not empty", "str2" -> "not empty").validate[Foo].asOpt.isDefined)
assert(!Json.obj("str1" -> "", "str2" -> "not empty").validate[Foo].asOpt.isDefined)
assert(Json.obj("str1" -> "not empty", "str2" -> "").validate[Foo].asOpt.isDefined)
assert(!Json.obj("str1" -> "", "str2" -> "").validate[Foo].asOpt.isDefined)
assert(Json.obj("str1" -> "not empty", "str2" -> "").as[Foo].str1.isInstanceOf[String])
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment