diff options
author | Johannes Rudolph <johannes_rudolph@gmx.de> | 2012-05-29 17:29:45 +0200 |
---|---|---|
committer | Johannes Rudolph <johannes_rudolph@gmx.de> | 2012-05-29 17:29:45 +0200 |
commit | 6e50bcf8c62e153667921f92fd8af95c913066c2 (patch) | |
tree | c9bc82865979ff0449d449d0c4cbcc02eb156bb7 /src/main/scala/cc | |
parent | 1a992f3b4eea1da49d9d6f36ddcb6faeef7340ca (diff) | |
download | spray-json-6e50bcf8c62e153667921f92fd8af95c913066c2.tar.gz spray-json-6e50bcf8c62e153667921f92fd8af95c913066c2.tar.bz2 spray-json-6e50bcf8c62e153667921f92fd8af95c913066c2.zip |
enable nested finding
Diffstat (limited to 'src/main/scala/cc')
-rw-r--r-- | src/main/scala/cc/spray/json/JsonLenses.scala | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/src/main/scala/cc/spray/json/JsonLenses.scala b/src/main/scala/cc/spray/json/JsonLenses.scala index 7a5c731..ae197b6 100644 --- a/src/main/scala/cc/spray/json/JsonLenses.scala +++ b/src/main/scala/cc/spray/json/JsonLenses.scala @@ -73,10 +73,11 @@ object JsonLenses { def apply(value: SafeJsValue): SafeJsValue } - trait Projection[M[_]] { - type ThenScalar - + trait Updateable { def updated(f: SafeJsValue => SafeJsValue)(parent: JsValue): SafeJsValue + } + trait Projection[M[_]] extends Updateable { + type ThenScalar def retr: JsValue => Validated[M[JsValue]] def mapValue[T](value: M[JsValue])(f: JsValue => Validated[T]): Validated[M[T]] @@ -125,7 +126,7 @@ object JsonLenses { type SeqProjection = Projection[Seq] - trait ProjectionImpl[M[_]] extends Projection[M] { + trait ProjectionImpl[M[_]] extends Projection[M] { outer => def getSecure[T: MonadicReader]: JsValue => Validated[M[T]] = p => retr(p).flatMap(mapValue(_)(_.as[T])) @@ -136,6 +137,11 @@ object JsonLenses { def apply(parent: JsValue): JsValue = updated(op(_))(parent).getOrThrow } + + abstract class Joined(next: Updateable) extends Updateable { + def updated(f: SafeJsValue => SafeJsValue)(parent: JsValue): SafeJsValue = + outer.updated(_.flatMap(next.updated(f)))(parent) + } } trait ScalarProjectionImpl extends ScalarProjection with ProjectionImpl[Id] { outer => @@ -146,33 +152,57 @@ object JsonLenses { value => getSecure[U] apply value exists f def andThen(next: ScalarProjection): ScalarProjection = - new ScalarProjectionImpl { - def updated(f: SafeJsValue => SafeJsValue)(parent: JsValue): SafeJsValue = - outer.updated(_.flatMap(next.updated(f)))(parent) - + new Joined(next) with ScalarProjectionImpl { def retr: JsValue => SafeJsValue = parent => for { outerV <- outer.retr(parent) innerV <- next.retr(outerV) } yield innerV - } - def andThen(next: OptProjection): OptProjection = ??? + def andThen(next: OptProjection): OptProjection = new Joined(next) with OptProjectionImpl { + def retr: JsValue => Validated[Option[JsValue]] = parent => + for { + outerV <- outer.retr(parent) + innerV <- next.retr(outerV) + } yield innerV + } } - trait OptProjectionImpl extends OptProjection with ProjectionImpl[Option] { + trait OptProjectionImpl extends OptProjection with ProjectionImpl[Option] { outer => def mapValue[T](value: Option[JsValue])(f: JsValue => Validated[T]): Validated[Option[T]] = - value.map(f) match { + swap(value.map(f)) + + def is[U: MonadicReader](f: U => Boolean): JsPred = ??? + + def andThen(next: ScalarProjection): OptProjection = new Joined(next) with OptProjectionImpl { + def retr: JsValue => Validated[Option[JsValue]] = parent => + for { + outerV <- outer.retr(parent) + innerV <- swap(outerV.map(next.retr)) + } yield innerV + } + def andThen(next: OptProjection): OptProjection = new Joined(next) with OptProjectionImpl { + def retr: JsValue => Validated[Option[JsValue]] = parent => + for { + outerV <- outer.retr(parent) + innerV <- swap(outerV.flatMap(x => swap(next.retr(x)))) + } yield innerV + } + + def swap[T](v: Option[Validated[T]]): Validated[Option[T]] = + v match { case None => Right(None) case Some(Right(x)) => Right(Some(x)) case Some(Left(e)) => Left(e) } - def is[U: MonadicReader](f: U => Boolean): JsPred = ??? - - def andThen(next: ScalarProjection): OptProjection = ??? - def andThen(next: OptProjection): OptProjection = ??? + def swap[T](v: Validated[Option[T]]): Option[Validated[T]] = + v match { + case Right(None) => None + case Right(Some(v)) => Some(Right(v)) + case Left(e) => Some(Left(e)) + } } def field(name: String): ScalarProjection = new ScalarProjectionImpl { |