Skip to content

Instantly share code, notes, and snippets.

@VlachJosef
Created November 11, 2015 12:08
Show Gist options
  • Save VlachJosef/0ca136702a7cd4af1032 to your computer and use it in GitHub Desktop.
Save VlachJosef/0ca136702a7cd4af1032 to your computer and use it in GitHub Desktop.
Using tagged type with play-json
package funkypandagame
import org.scalatest.FlatSpec
import org.scalatest.Matchers
import play.api.libs.json._
import shapeless.tag
import shapeless.tag.@@
sealed trait IdTag
sealed trait NameTag
case class User(id: Long @@ IdTag, name: String, nameId: String @@ NameTag)
class TaggedSuiteShapeless extends FlatSpec with Matchers {
implicit def taggedLongFormat[T]: Format[Long @@ T] = new Format[Long @@ T] {
def reads(json: JsValue): JsResult[Long @@ T] = json match {
case JsNumber(v) => JsSuccess(tag[T](v.toLong))
case unknown => JsError(s"Number value expected, got: $unknown")
}
def writes(v: Long @@ T): JsValue = JsNumber(v)
}
implicit def taggedStringFormat[T]: Format[String @@ T] = new Format[String @@ T] {
def reads(json: JsValue): JsResult[String @@ T] = json match {
case JsString(v) => JsSuccess(tag[T](v))
case unknown => JsError(s"String value expected, got: $unknown")
}
def writes(v: String @@ T): JsValue = JsString(v)
}
implicit val userFormat = Json.format[User]
"User containing tagged type" should "be convertible to String from case class" in {
val user = User(tag[IdTag](1L), "John", tag[NameTag]("Doe"))
val userJson = Json.toJson(user)
val userString = Json.prettyPrint(userJson)
userString should be(
"""|{
| "id" : 1,
| "name" : "John",
| "nameId" : "Doe"
|}""".stripMargin)
}
it should "be convertible to case class from String" in {
val userString = """|{
| "id" : 1,
| "name" : "John",
| "nameId" : "Doe"
|}""".stripMargin
val user = Json.fromJson[User](Json.parse(userString))
user.get should be (User(tag[IdTag](1L), "John", tag[NameTag]("Doe")))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment