Skip to content

Commit

Permalink
coerce string to int or long for play json
Browse files Browse the repository at this point in the history
  • Loading branch information
beezee committed May 6, 2016
1 parent c4673ff commit d31e7b7
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 2 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ lazy val playjsonTypify = project.in(file("play-json-typify"))
.dependsOn(typifyJVM)
.settings(
name := "play-json-typify",
version := "1.0.2",
version := "1.0.3",
scalaVersion := "2.11.8",
scalacOptions ++= scalacF,
licenses += ("Apache-2.0", url("http://www.apache.org/licenses/LICENSE-2.0")),
Expand Down
61 changes: 61 additions & 0 deletions play-json-typify/src/main/scala/PlayJsonTypify.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import typify.{CanParse, Parsed, ParseError}
import scala.reflect.ClassTag
import scalaz.syntax.nel._
import scalaz.syntax.std.option._
import scalaz.syntax.std.string._
import scalaz.syntax.validation._
import scalaz.ValidationNel

Expand Down Expand Up @@ -40,4 +41,64 @@ object parsedinstances extends CatchAllInstance {
s"Could not be interpreted as Option[${ct.toString}]"))
}
}

implicit lazy val pi = new CanParse[Int, JsValue] {
def parse(k: String, jv: JsValue)(implicit ct: ClassTag[Int]) =
(jv \ k).asOpt[Int]
.orElse((jv \ k).asOpt[String].flatMap(_.parseInt.toOption))
.toSuccessNel(ParseError(k, s"Could not be parsed as Int"))

def as(jv: JsValue)(implicit ct: ClassTag[Int]) =
jv.asOpt[Int]
.orElse(jv.asOpt[String].flatMap(_.parseInt.toOption))
.toSuccessNel(ParseError("_root_", s"Could not be interpreted as Int"))
}

implicit lazy val pio = new CanParse[Option[Int], JsValue] {
def parse(k: String, jv: JsValue)(implicit ct: ClassTag[Option[Int]]):
ValidationNel[ParseError, Option[Int]] = (jv \ k) match {
case _: JsUndefined => None.successNel[ParseError]
case JsDefined(r) => as(r)
}

def as(jv: JsValue)(implicit ct: ClassTag[Option[Int]]):
ValidationNel[ParseError, Option[Int]] = jv match {
case JsNull => None.successNel[ParseError]
case s: JsValue => s.asOpt[Int]
.orElse(s.asOpt[String].flatMap(_.parseInt.toOption))
.map(Some(_))
.toSuccessNel(ParseError("_root_",
s"Could not be interpreted as Option[Int]"))
}
}

implicit lazy val pl = new CanParse[Long, JsValue] {
def parse(k: String, jv: JsValue)(implicit ct: ClassTag[Long]) =
(jv \ k).asOpt[Long]
.orElse((jv \ k).asOpt[String].flatMap(_.parseLong.toOption))
.toSuccessNel(ParseError(k, s"Could not be parsed as Long"))

def as(jv: JsValue)(implicit ct: ClassTag[Long]) =
jv.asOpt[Long]
.orElse(jv.asOpt[String].flatMap(_.parseLong.toOption))
.toSuccessNel(ParseError("_root_", s"Could not be interpreted as Long"))
}

implicit lazy val plo = new CanParse[Option[Long], JsValue] {
def parse(k: String, jv: JsValue)(implicit ct: ClassTag[Option[Long]]):
ValidationNel[ParseError, Option[Long]] = (jv \ k) match {
case _: JsUndefined => None.successNel[ParseError]
case JsDefined(r) => as(r)
}

def as(jv: JsValue)(implicit ct: ClassTag[Option[Long]]):
ValidationNel[ParseError, Option[Long]] = jv match {
case JsNull => None.successNel[ParseError]
case s: JsValue => s.asOpt[Long]
.orElse(s.asOpt[String].flatMap(_.parseLong.toOption))
.map(Some(_))
.toSuccessNel(ParseError("_root_",
s"Could not be interpreted as Option[Long]"))
}
}
}
2 changes: 1 addition & 1 deletion play-json-typify/src/test/scala/Example.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ object PlayJsonExample extends App {

case class Optional[A](a: Option[A])
case class Mandatory[A](a: A)
val valid = parse("""{"a":{"email":"foo@opman","age":22,"gender":"m","session":77777}}""")
val valid = parse("""{"a":{"email":"foo@opman","age":"22","gender":"m","session":"77777"}}""")

println(typify[Optional[Person]](valid))
println(typify[Optional[Person]](parse("null")))
Expand Down

0 comments on commit d31e7b7

Please sign in to comment.