summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMathias <mathias@spray.cc>2012-01-19 16:48:46 +0100
committerMathias <mathias@spray.cc>2012-02-01 11:01:18 +0100
commitc6b5edcb5665b0ef60b5108d8cff3431c0663927 (patch)
tree3c5641f3a1c351364e068ba54692e1370697661e /src
parent8e6d79cfc3080c276890a2653c545dade6387cf8 (diff)
downloadspray-json-c6b5edcb5665b0ef60b5108d8cff3431c0663927.tar.gz
spray-json-c6b5edcb5665b0ef60b5108d8cff3431c0663927.tar.bz2
spray-json-c6b5edcb5665b0ef60b5108d8cff3431c0663927.zip
Add jsonFormatX overloads providing automatic case class field name extraction
Conflicts: src/main/scala/cc/spray/json/ProductFormats.scala
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/cc/spray/json/ProductFormats.scala132
-rw-r--r--src/test/scala/cc/spray/json/ProductFormatsSpec.scala4
2 files changed, 112 insertions, 24 deletions
diff --git a/src/main/scala/cc/spray/json/ProductFormats.scala b/src/main/scala/cc/spray/json/ProductFormats.scala
index 6a79f5f..1f26259 100644
--- a/src/main/scala/cc/spray/json/ProductFormats.scala
+++ b/src/main/scala/cc/spray/json/ProductFormats.scala
@@ -23,7 +23,11 @@ package cc.spray.json
trait ProductFormats {
this: StandardFormats =>
- def jsonFormat[A :JF, T <: Product](construct: A => T, a: String) = new RootJsonFormat[T]{
+ def jsonFormat1[A :JF, T <: Product :ClassManifest](construct: A => T): RootJsonFormat[T] = {
+ val Array(a) = extractFieldNames(classManifest[T])
+ jsonFormat(construct, a)
+ }
+ def jsonFormat[A :JF, T <: Product](construct: A => T, a: String): RootJsonFormat[T] = new RootJsonFormat[T]{
def write(p: T) = JsObject(
productElement2Field[A](a, p, 0)
)
@@ -32,7 +36,11 @@ trait ProductFormats {
)
}
- def jsonFormat[A :JF, B :JF, T <: Product](construct: (A, B) => T, a: String, b: String) = new RootJsonFormat[T]{
+ def jsonFormat2[A :JF, B :JF, T <: Product :ClassManifest](construct: (A, B) => T): RootJsonFormat[T] = {
+ val Array(a, b) = extractFieldNames(classManifest[T])
+ jsonFormat(construct, a, b)
+ }
+ def jsonFormat[A :JF, B :JF, T <: Product](construct: (A, B) => T, a: String, b: String): RootJsonFormat[T] = new RootJsonFormat[T]{
def write(p: T) = JsObject(
productElement2Field[A](a, p, 0,
productElement2Field[B](b, p, 1))
@@ -43,8 +51,12 @@ trait ProductFormats {
)
}
+ def jsonFormat3[A :JF, B :JF, C :JF, T <: Product :ClassManifest](construct: (A, B, C) => T): RootJsonFormat[T] = {
+ val Array(a, b, c) = extractFieldNames(classManifest[T])
+ jsonFormat(construct, a, b, c)
+ }
def jsonFormat[A :JF, B :JF, C :JF, T <: Product](construct: (A, B, C) => T,
- a: String, b: String, c: String) = new RootJsonFormat[T]{
+ a: String, b: String, c: String): RootJsonFormat[T] = new RootJsonFormat[T]{
def write(p: T) = JsObject(
productElement2Field[A](a, p, 0,
productElement2Field[B](b, p, 1,
@@ -57,8 +69,13 @@ trait ProductFormats {
)
}
+ def jsonFormat4[A :JF, B :JF, C :JF, D :JF, T <: Product :ClassManifest]
+ (construct: (A, B, C, D) => T): RootJsonFormat[T] = {
+ val Array(a, b, c, d) = extractFieldNames(classManifest[T])
+ jsonFormat(construct, a, b, c, d)
+ }
def jsonFormat[A :JF, B :JF, C :JF, D :JF, T <: Product](construct: (A, B, C, D) => T,
- a: String, b: String, c: String, d: String) = new RootJsonFormat[T]{
+ a: String, b: String, c: String, d: String): RootJsonFormat[T] = new RootJsonFormat[T]{
def write(p: T) = JsObject(
productElement2Field[A](a, p, 0,
productElement2Field[B](b, p, 1,
@@ -73,8 +90,13 @@ trait ProductFormats {
)
}
+ def jsonFormat5[A :JF, B :JF, C :JF, D :JF, E :JF, T <: Product :ClassManifest]
+ (construct: (A, B, C, D, E) => T): RootJsonFormat[T] = {
+ val Array(a, b, c, d, e) = extractFieldNames(classManifest[T])
+ jsonFormat(construct, a, b, c, d, e)
+ }
def jsonFormat[A :JF, B :JF, C :JF, D :JF, E :JF, T <: Product](construct: (A, B, C, D, E) => T,
- a: String, b: String, c: String, d: String, e: String) = new RootJsonFormat[T]{
+ a: String, b: String, c: String, d: String, e: String): RootJsonFormat[T] = new RootJsonFormat[T]{
def write(p: T) = JsObject(
productElement2Field[A](a, p, 0,
productElement2Field[B](b, p, 1,
@@ -90,9 +112,14 @@ trait ProductFormats {
fromField[E](value, e)
)
}
-
+
+ def jsonFormat6[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, T <: Product :ClassManifest]
+ (construct: (A, B, C, D, E, F) => T): RootJsonFormat[T] = {
+ val Array(a, b, c, d, e, f) = extractFieldNames(classManifest[T])
+ jsonFormat(construct, a, b, c, d, e, f)
+ }
def jsonFormat[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, T <: Product](construct: (A, B, C, D, E, F) => T,
- a: String, b: String, c: String, d: String, e: String, f: String) = new RootJsonFormat[T]{
+ a: String, b: String, c: String, d: String, e: String, f: String): RootJsonFormat[T] = new RootJsonFormat[T]{
def write(p: T) = JsObject(
productElement2Field[A](a, p, 0,
productElement2Field[B](b, p, 1,
@@ -110,9 +137,14 @@ trait ProductFormats {
fromField[F](value, f)
)
}
-
+
+ def jsonFormat7[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, T <: Product :ClassManifest]
+ (construct: (A, B, C, D, E, F, G) => T): RootJsonFormat[T] = {
+ val Array(a, b, c, d, e, f, g) = extractFieldNames(classManifest[T])
+ jsonFormat(construct, a, b, c, d, e, f, g)
+ }
def jsonFormat[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, T <: Product](construct: (A, B, C, D, E, F, G) => T,
- a: String, b: String, c: String, d: String, e: String, f: String, g: String) = new RootJsonFormat[T]{
+ a: String, b: String, c: String, d: String, e: String, f: String, g: String): RootJsonFormat[T] = new RootJsonFormat[T]{
def write(p: T) = JsObject(
productElement2Field[A](a, p, 0,
productElement2Field[B](b, p, 1,
@@ -132,10 +164,15 @@ trait ProductFormats {
fromField[G](value, g)
)
}
-
+
+ def jsonFormat8[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, H :JF, T <: Product :ClassManifest]
+ (construct: (A, B, C, D, E, F, G, H) => T): RootJsonFormat[T] = {
+ val Array(a, b, c, d, e, f, g, h) = extractFieldNames(classManifest[T])
+ jsonFormat(construct, a, b, c, d, e, f, g, h)
+ }
def jsonFormat[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, H :JF, T <: Product]
(construct: (A, B, C, D, E, F, G, H) => T,
- a: String, b: String, c: String, d: String, e: String, f: String, g: String, h: String) = new RootJsonFormat[T]{
+ a: String, b: String, c: String, d: String, e: String, f: String, g: String, h: String): RootJsonFormat[T] = new RootJsonFormat[T]{
def write(p: T) = JsObject(
productElement2Field[A](a, p, 0,
productElement2Field[B](b, p, 1,
@@ -157,10 +194,15 @@ trait ProductFormats {
fromField[H](value, h)
)
}
-
+
+ def jsonFormat9[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, H :JF, I :JF, T <: Product :ClassManifest]
+ (construct: (A, B, C, D, E, F, G, H, I) => T): RootJsonFormat[T] = {
+ val Array(a, b, c, d, e, f, g, h, i) = extractFieldNames(classManifest[T])
+ jsonFormat(construct, a, b, c, d, e, f, g, h, i)
+ }
def jsonFormat[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, H :JF, I :JF, T <: Product]
(construct: (A, B, C, D, E, F, G, H, I) => T, a: String, b: String, c: String, d: String, e: String, f: String,
- g: String, h: String, i: String) = new RootJsonFormat[T]{
+ g: String, h: String, i: String): RootJsonFormat[T] = new RootJsonFormat[T]{
def write(p: T) = JsObject(
productElement2Field[A](a, p, 0,
productElement2Field[B](b, p, 1,
@@ -184,10 +226,15 @@ trait ProductFormats {
fromField[I](value, i)
)
}
-
+
+ def jsonFormat10[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, H :JF, I :JF, J :JF, T <: Product :ClassManifest]
+ (construct: (A, B, C, D, E, F, G, H, I, J) => T): RootJsonFormat[T] = {
+ val Array(a, b, c, d, e, f, g, h, i, j) = extractFieldNames(classManifest[T])
+ jsonFormat(construct, a, b, c, d, e, f, g, h, i, j)
+ }
def jsonFormat[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, H :JF, I :JF, J :JF, T <: Product]
(construct: (A, B, C, D, E, F, G, H, I, J) => T, a: String, b: String, c: String, d: String, e: String,
- f: String, g: String, h: String, i: String, j: String) = new RootJsonFormat[T]{
+ f: String, g: String, h: String, i: String, j: String): RootJsonFormat[T] = new RootJsonFormat[T]{
def write(p: T) = JsObject(
productElement2Field[A](a, p, 0,
productElement2Field[B](b, p, 1,
@@ -213,10 +260,15 @@ trait ProductFormats {
fromField[J](value, j)
)
}
-
+
+ def jsonFormat11[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, H :JF, I :JF, J :JF, K :JF, T <: Product :ClassManifest]
+ (construct: (A, B, C, D, E, F, G, H, I, J, K) => T): RootJsonFormat[T] = {
+ val Array(a, b, c, d, e, f, g, h, i, j, k) = extractFieldNames(classManifest[T])
+ jsonFormat(construct, a, b, c, d, e, f, g, h, i, j, k)
+ }
def jsonFormat[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, H :JF, I :JF, J :JF, K :JF, T <: Product]
(construct: (A, B, C, D, E, F, G, H, I, J, K) => T, a: String, b: String, c: String, d: String, e: String,
- f: String, g: String, h: String, i: String, j: String, k: String) = new RootJsonFormat[T]{
+ f: String, g: String, h: String, i: String, j: String, k: String): RootJsonFormat[T] = new RootJsonFormat[T]{
def write(p: T) = JsObject(
productElement2Field[A](a, p, 0,
productElement2Field[B](b, p, 1,
@@ -245,9 +297,14 @@ trait ProductFormats {
)
}
+ def jsonFormat12[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, H :JF, I :JF, J :JF, K :JF, L: JF, T <: Product :ClassManifest]
+ (construct: (A, B, C, D, E, F, G, H, I, J, K, L) => T): RootJsonFormat[T] = {
+ val Array(a, b, c, d, e, f, g, h, i, j, k, l) = extractFieldNames(classManifest[T])
+ jsonFormat(construct, a, b, c, d, e, f, g, h, i, j, k, l)
+ }
def jsonFormat[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, H :JF, I :JF, J :JF, K :JF, L :JF, T <: Product]
(construct: (A, B, C, D, E, F, G, H, I, J, K, L) => T, a: String, b: String, c: String, d: String, e: String,
- f: String, g: String, h: String, i: String, j: String, k: String, l: String) = new RootJsonFormat[T]{
+ f: String, g: String, h: String, i: String, j: String, k: String, l: String): RootJsonFormat[T] = new RootJsonFormat[T]{
def write(p: T) = JsObject(
productElement2Field[A](a, p, 0,
productElement2Field[B](b, p, 1,
@@ -278,9 +335,14 @@ trait ProductFormats {
)
}
+ def jsonFormat13[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, H :JF, I :JF, J :JF, K :JF, L: JF, M :JF, T <: Product :ClassManifest]
+ (construct: (A, B, C, D, E, F, G, H, I, J, K, L, M) => T): RootJsonFormat[T] = {
+ val Array(a, b, c, d, e, f, g, h, i, j, k, l, m) = extractFieldNames(classManifest[T])
+ jsonFormat(construct, a, b, c, d, e, f, g, h, i, j, k, l, m)
+ }
def jsonFormat[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, H :JF, I :JF, J :JF, K :JF, L :JF, M :JF, T <: Product]
(construct: (A, B, C, D, E, F, G, H, I, J, K, L, M) => T, a: String, b: String, c: String, d: String, e: String,
- f: String, g: String, h: String, i: String, j: String, k: String, l: String, m: String) = new RootJsonFormat[T]{
+ f: String, g: String, h: String, i: String, j: String, k: String, l: String, m: String): RootJsonFormat[T] = new RootJsonFormat[T]{
def write(p: T) = JsObject(
productElement2Field[A](a, p, 0,
productElement2Field[B](b, p, 1,
@@ -313,10 +375,15 @@ trait ProductFormats {
)
}
+ def jsonFormat14[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, H :JF, I :JF, J :JF, K :JF, L: JF, M :JF, N :JF, T <: Product :ClassManifest]
+ (construct: (A, B, C, D, E, F, G, H, I, J, K, L, M, N) => T): RootJsonFormat[T] = {
+ val Array(a, b, c, d, e, f, g, h, i, j, k, l, m, n) = extractFieldNames(classManifest[T])
+ jsonFormat(construct, a, b, c, d, e, f, g, h, i, j, k, l, m, n)
+ }
def jsonFormat[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, H :JF, I :JF, J :JF, K :JF, L :JF, M :JF, N :JF, T <: Product]
(construct: (A, B, C, D, E, F, G, H, I, J, K, L, M, N) => T, a: String, b: String, c: String, d: String,
e: String, f: String, g: String, h: String, i: String, j: String, k: String, l: String, m: String,
- n: String) = new RootJsonFormat[T]{
+ n: String): RootJsonFormat[T] = new RootJsonFormat[T]{
def write(p: T) = JsObject(
productElement2Field[A](a, p, 0,
productElement2Field[B](b, p, 1,
@@ -351,10 +418,15 @@ trait ProductFormats {
)
}
+ def jsonFormat15[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, H :JF, I :JF, J :JF, K :JF, L: JF, M :JF, N :JF, O :JF, T <: Product :ClassManifest]
+ (construct: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => T): RootJsonFormat[T] = {
+ val Array(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = extractFieldNames(classManifest[T])
+ jsonFormat(construct, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
+ }
def jsonFormat[A :JF, B :JF, C :JF, D :JF, E :JF, F :JF, G :JF, H :JF, I :JF, J :JF, K :JF, L :JF, M :JF, N :JF, O :JF, T <: Product]
(construct: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => T, a: String, b: String, c: String, d: String,
e: String, f: String, g: String, h: String, i: String, j: String, k: String, l: String, m: String, n: String,
- o: String) = new RootJsonFormat[T]{
+ o: String): RootJsonFormat[T] = new RootJsonFormat[T]{
def write(p: T) = JsObject(
productElement2Field[A](a, p, 0,
productElement2Field[B](b, p, 1,
@@ -401,7 +473,7 @@ trait ProductFormats {
case _ => (fieldName, writer.write(value)) :: rest
}
}
-
+
private def fromField[T](value: JsValue, fieldName: String)(implicit reader: JsonReader[T]) = {
value match {
case x: JsObject =>
@@ -419,6 +491,22 @@ trait ProductFormats {
case _ => deserializationError("Object expected")
}
}
+
+ protected def extractFieldNames(classManifest: ClassManifest[_]): Array[String] = {
+ val clazz = classManifest.erasure
+ try {
+ val copyDefaultMethods = clazz.getMethods.filter(_.getName.startsWith("copy$default$"))
+ val fields = clazz.getDeclaredFields.filterNot(_.getName.startsWith("$"))
+ if (copyDefaultMethods.length != fields.length)
+ sys.error("Case class declares additional fields")
+ if (fields.zip(copyDefaultMethods).exists { case (f, m) => f.getType != m.getReturnType })
+ sys.error("Cannot determine field order")
+ fields.map(_.getName)
+ } catch {
+ case ex => throw new RuntimeException("Cannot automatically determine case class field names and order, " +
+ "please use the 'jsonFormat' overload with explicit field name specification", ex)
+ }
+ }
}
/**
diff --git a/src/test/scala/cc/spray/json/ProductFormatsSpec.scala b/src/test/scala/cc/spray/json/ProductFormatsSpec.scala
index 6ec1611..c34f491 100644
--- a/src/test/scala/cc/spray/json/ProductFormatsSpec.scala
+++ b/src/test/scala/cc/spray/json/ProductFormatsSpec.scala
@@ -25,8 +25,8 @@ class ProductFormatsSpec extends Specification {
trait TestProtocol {
this: DefaultJsonProtocol =>
- implicit val test2Format = jsonFormat(Test2, "a", "b")
- implicit def test3Format[A: JsonFormat, B: JsonFormat] = jsonFormat(Test3.apply[A, B], "as", "bs")
+ implicit val test2Format = jsonFormat2(Test2)
+ implicit def test3Format[A: JsonFormat, B: JsonFormat] = jsonFormat2(Test3.apply[A, B])
}
object TestProtocol1 extends DefaultJsonProtocol with TestProtocol
object TestProtocol2 extends DefaultJsonProtocol with TestProtocol with NullOptions