Skip to content

Instantly share code, notes, and snippets.

@ovstetun
Forked from xuwei-k/Main.scala
Last active December 22, 2015 14:18
Show Gist options
  • Save ovstetun/6484405 to your computer and use it in GitHub Desktop.
Save ovstetun/6484405 to your computer and use it in GitHub Desktop.
libraryDependencies ++= Seq(
"org.json4s" %% "json4s-scalaz" % "3.2.5",
"org.json4s" %% "json4s-native" % "3.2.5"
)
scalaVersion := "2.10.2"
/**
* https://github.com/json4s/json4s/issues/39
*
* Validation Monad instance removed from Scalaz7.
* https://github.com/scalaz/scalaz/blob/v6.0.4/core/src/main/scala/scalaz/Validation.scala#L133-L147
*
* need explicitly convert to `scalaz.\/` (aka disjunction) if you want use the `Kleisli` composition
*/
object Main extends App {
import scalaz._
import Scalaz._
import org.json4s.scalaz.JsonScalaz._
import org.json4s._
import org.json4s.native.JsonMethods._
case class Address(street: String, zipCode: String)
case class Person(name: String, age: Int, address: Address)
val json = parse(""" {"street": "Manhattan 2", "zip": "00223" } """)
val address1 = (field[String]("street")(json) |@| field[String]("zip")(json)) { Address }
println(address1)
val address2 = (field[String]("streets")(json) |@| field[String]("zip")(json)) { Address }
println(address2)
val address3 = Address.applyJSON(field[String]("street"), field[String]("zip"))(json)
println(address3)
implicit def addrJSONR: JSONR[Address] = Address.applyJSON(field[String]("street"), field[String]("zip"))
val p = parse(""" {"name":"Average Joe","age":34,"address":{"street": "Manhattan 2", "zip": "00223" }} """)
val p2 = parse(""" {"name":"Young Joe","age":17,"address":{"street": "Manhattan 2", "zip": "00223" }} """)
val p3 = parse(""" {"name":"Old Joe","age":61,"address":{"street": "Manhattan 2", "zip": "00223" }} """)
val person1 = Person.applyJSON(field[String]("name"), field[Int]("age"), field[Address]("address"))(p)
println(person1)
def min(x: Int): Int => Result[Int] = (y: Int) =>
if (y < x) Fail("min", y + " < " + x) else y.success
def max(x: Int): Int => Result[Int] = (y: Int) =>
if (y > x) Fail("max", y + " > " + x) else y.success
type EitherNel[+a] = NonEmptyList[Error] \/ a
def validate[A: JSONR](name: String) = Kleisli(field[A](name)).mapK[EitherNel, A](_.disjunction)
implicit def function2EitherNel[A](f: A => Result[A]): (A => EitherNel[A]) = (a: A) => f(a).disjunction
implicit def kleisli2Result[A](v: Kleisli[EitherNel, JValue, A]): JValue => Result[A] = (v.run _).andThen(_.validation)
val ageValidator1 = validate[Int]("age")
val ageValidator2 = {i: Int => (min(18)(i) |@| max(60)(i))((a, _) => a).disjunction}
val ageValidator = ((ageValidator1 >==> ageValidator2).run _).andThen(_.validation)
val person2 = Person.applyJSON(field[String]("name"), ageValidator, field[Address]("address"))
println(person2(p))
println(person2(p2))
println(person2(p3))
val person3 = Person.applyJSON(field[String]("name"), validate[Int]("age") >==> min(18) >==> max(60) , field[Address]("address"))
println(person3(p))
println(person3(p2))
println(person3(p3))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment