From d0267d032a82508d703e5331d92e5e490591f268 Mon Sep 17 00:00:00 2001 From: Mathias Date: Tue, 23 Aug 2011 16:19:53 +0200 Subject: Add test for generic functionality, add description to README --- README.markdown | 13 +++++++++++- .../scala/cc/spray/json/ProductFormatsSpec.scala | 23 +++++++++++++++++++--- 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 + } + } + } -- cgit v1.2.3