summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias <mathias@spray.cc>2011-08-23 16:19:53 +0200
committerMathias <mathias@spray.cc>2011-08-23 16:26:41 +0200
commitd0267d032a82508d703e5331d92e5e490591f268 (patch)
treedeaeada7843096e026063aa46731a9b2005bd305
parent253b8017cf6a5b07f523255f5f82ce0e05361b1b (diff)
downloadspray-json-d0267d032a82508d703e5331d92e5e490591f268.tar.gz
spray-json-d0267d032a82508d703e5331d92e5e490591f268.tar.bz2
spray-json-d0267d032a82508d703e5331d92e5e490591f268.zip
Add test for generic functionality, add description to README
-rw-r--r--README.markdown13
-rw-r--r--src/test/scala/cc/spray/json/ProductFormatsSpec.scala23
2 files changed, 32 insertions, 4 deletions
diff --git a/README.markdown b/README.markdown
index 9b150ea..ef48db5 100644
--- a/README.markdown
+++ b/README.markdown
@@ -94,7 +94,18 @@ If your custom type `T` is a case class then augmenting the `DefaultJsonProtocol
val json = Color("CadetBlue", 95, 158, 160).toJson
val color = json.fromJson[Color]
-The `jsonFormat` method reduces the boilerplate to a minimum, just pass it the companion object of your case class as well as the field names (in order) and it will return a ready-to-use `JsonFormat` for your type.
+The `jsonFormat` method reduces the boilerplate to a minimum, just pass it the companion object of your case class as
+well as the field names (in order) and it will return a ready-to-use `JsonFormat` for your type.
+
+If your case class is generic in that it takes type parameters itself the `jsonFormat` method can also help you.
+However, there is a little something more boilerplate required as you need to add context bounds for all type parameters
+and explicitly refer to the case classes `apply` method as in this example:
+
+ case class NamedList[A](name: String, items: List[A])
+
+ object MyJsonProtocol extends DefaultJsonProtocol {
+ implicit def namedListFormat[A :JsonFormat] = jsonFormat(NamedList.apply[A], "name", "items")
+ }
### Providing JsonFormats for other Types
diff --git a/src/test/scala/cc/spray/json/ProductFormatsSpec.scala b/src/test/scala/cc/spray/json/ProductFormatsSpec.scala
index 09b188e..edd2481 100644
--- a/src/test/scala/cc/spray/json/ProductFormatsSpec.scala
+++ b/src/test/scala/cc/spray/json/ProductFormatsSpec.scala
@@ -5,9 +5,12 @@ import org.specs2.mutable._
class ProductFormatsSpec extends Specification with DefaultJsonProtocol {
case class Test2(a: Int, b: Double)
- implicit val test2Format = jsonFormat(Test2, "a", "b")
+ implicit val test2Format = jsonFormat(Test2, "a", "b")
+
+ case class Test3[A, B](as: List[A], bs: List[B])
+ implicit def test3Format[A: JsonFormat, B: JsonFormat] = jsonFormat(Test3.apply[A, B], "as", "bs")
- "A JsonFormat created with format, for a case class with 2 elements," should {
+ "A JsonFormat created with `jsonFormat`, for a case class with 2 elements," should {
val obj = Test2(42, 4.2)
val json = JsObject(JsField("a", 42), JsField("b", 4.2))
"convert to a respective JsObject" in {
@@ -27,5 +30,19 @@ class ProductFormatsSpec extends Specification with DefaultJsonProtocol {
JsNull.fromJson[Test2] must throwA(new DeserializationException("Object expected"))
)
}
-
+
+ "A JsonFormat for a generic case class and created with `jsonFormat`" should {
+ val obj = Test3(42 :: 43 :: Nil, "x" :: "y" :: "z" :: Nil)
+ val json = JsObject(
+ JsField("as", JsArray(JsNumber(42), JsNumber(43))),
+ JsField("bs", JsArray(JsString("x"), JsString("y"), JsString("z")))
+ )
+ "convert to a respective JsObject" in {
+ obj.toJson mustEqual json
+ }
+ "convert a JsObject to the respective case class instance" in {
+ json.fromJson[Test3[Int, String]] mustEqual obj
+ }
+ }
+
}