summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMathias <mathias@spray.cc>2011-05-23 14:12:53 +0200
committerMathias <mathias@spray.cc>2011-05-23 14:12:53 +0200
commit03e9e1a6d50f6afb7848033ad4ca1f5239943a2f (patch)
tree1605235adc731bb247aa6b81f1da0f09a5b8a398 /src
parent25f696587cedc7aad2053cd50ca9da22e42c3146 (diff)
downloadspray-json-03e9e1a6d50f6afb7848033ad4ca1f5239943a2f.tar.gz
spray-json-03e9e1a6d50f6afb7848033ad4ca1f5239943a2f.tar.bz2
spray-json-03e9e1a6d50f6afb7848033ad4ca1f5239943a2f.zip
Add predefined JsonFormat for Either type
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/cc/spray/json/StandardFormats.scala25
-rw-r--r--src/test/scala/cc/spray/json/StandardFormatsSpec.scala19
2 files changed, 44 insertions, 0 deletions
diff --git a/src/main/scala/cc/spray/json/StandardFormats.scala b/src/main/scala/cc/spray/json/StandardFormats.scala
index 2a07d6c..20012b4 100644
--- a/src/main/scala/cc/spray/json/StandardFormats.scala
+++ b/src/main/scala/cc/spray/json/StandardFormats.scala
@@ -17,12 +17,24 @@
package cc.spray.json
+import scala.{Left, Right}
+
/**
* Provides the JsonFormats for the non-collection standard types.
*/
trait StandardFormats {
private type JF[T] = JsonFormat[T] // simple alias for reduced verbosity
+
+ def safeReader[A :JsonFormat] = new JsonReader[Either[Exception, A]] {
+ def read(json: JsValue) = {
+ try {
+ Right(json.fromJson)
+ } catch {
+ case e: Exception => Left(e)
+ }
+ }
+ }
implicit def optionFormat[T :JF] = new JF[Option[T]] {
def write(option: Option[T]) = option match {
@@ -34,6 +46,19 @@ trait StandardFormats {
case x => Some(x.fromJson)
}
}
+
+ implicit def eitherFormat[A :JF, B :JF] = new JF[Either[A, B]] {
+ def write(either: Either[A, B]) = either match {
+ case Right(a) => a.toJson
+ case Left(b) => b.toJson
+ }
+ def read(value: JsValue) = (value.fromJson(safeReader[A]), value.fromJson(safeReader[B])) match {
+ case (Right(a), _: Left[_, _]) => Left(a)
+ case (_: Left[_, _], Right(b)) => Right(b)
+ case (_: Right[_, _], _: Right[_, _]) => throw new DeserializationException("Ambiguous Either value: can be read as both, Left and Right, values")
+ case (Left(ea), Left(eb)) => throw new DeserializationException("Could not read Either value:\n" + ea + "---------- and ----------\n" + eb)
+ }
+ }
implicit def tuple1Format[A :JF] = new JF[Tuple1[A]] {
def write(t: Tuple1[A]) = t._1.toJson
diff --git a/src/test/scala/cc/spray/json/StandardFormatsSpec.scala b/src/test/scala/cc/spray/json/StandardFormatsSpec.scala
index 00561e0..7c454ac 100644
--- a/src/test/scala/cc/spray/json/StandardFormatsSpec.scala
+++ b/src/test/scala/cc/spray/json/StandardFormatsSpec.scala
@@ -1,6 +1,7 @@
package cc.spray.json
import org.specs.Specification
+import scala.Right
class StandardFormatsSpec extends Specification with StandardFormats with BasicFormats {
@@ -18,6 +19,24 @@ class StandardFormatsSpec extends Specification with StandardFormats with BasicF
JsString("Hello").fromJson[Option[String]] mustEqual Some("Hello")
}
}
+
+ "The eitherFormat" should {
+ val a: Either[Int, String] = Left(42)
+ val b: Either[Int, String] = Right("Hello")
+
+ "convert the left side of an Either value to Json" in {
+ a.toJson mustEqual JsNumber(42)
+ }
+ "convert the right side of an Either value to Json" in {
+ b.toJson mustEqual JsString("Hello")
+ }
+ "convert the left side of an Either value from Json" in {
+ JsNumber(42).fromJson[Either[Int, String]] mustEqual Left(42)
+ }
+ "convert the right side of an Either value from Json" in {
+ JsString("Hello").fromJson[Either[Int, String]] mustEqual Right("Hello")
+ }
+ }
"The tuple1Format" should {
"convert (42) to a JsNumber" in {