summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Bayne <mdb@samskivert.com>2012-02-24 15:43:36 -0800
committerMathias <mathias@spray.cc>2012-02-25 22:22:34 +0100
commit6f6cae9ad40ef8f6fbdd804443ac2624d6d48467 (patch)
tree2a70aff6e47642c81d96bb9630ba03d6f3259269 /src
parent49e49ee169ff86e4fcbb4f79667cf10788a8bd86 (diff)
downloadspray-json-6f6cae9ad40ef8f6fbdd804443ac2624d6d48467.tar.gz
spray-json-6f6cae9ad40ef8f6fbdd804443ac2624d6d48467.tar.bz2
spray-json-6f6cae9ad40ef8f6fbdd804443ac2624d6d48467.zip
Be more robust about ordering issues in extractFieldNames.
It is generally the case that JVMs will report field and method names in declaration order (though the spec says any order is OK). However, the Scala compiler feels no compunction whatsoever to put the copy$default$N methods into the AST in an order that will cause them to match the field declaration order. Running under JRebel, things get even hairier. This patch makes things work as long as field names are reported in order.
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/cc/spray/json/ProductFormats.scala11
1 files changed, 7 insertions, 4 deletions
diff --git a/src/main/scala/cc/spray/json/ProductFormats.scala b/src/main/scala/cc/spray/json/ProductFormats.scala
index 1f26259..7f7daac 100644
--- a/src/main/scala/cc/spray/json/ProductFormats.scala
+++ b/src/main/scala/cc/spray/json/ProductFormats.scala
@@ -495,7 +495,10 @@ trait ProductFormats {
protected def extractFieldNames(classManifest: ClassManifest[_]): Array[String] = {
val clazz = classManifest.erasure
try {
- val copyDefaultMethods = clazz.getMethods.filter(_.getName.startsWith("copy$default$"))
+ // copy methods have the form copy$default$N(), we need to sort them in order, but must account for the fact
+ // that lexical sorting of ...8(), ...9(), ...10() is not correct, so we extract N and sort by N.toInt
+ val copyDefaultMethods = clazz.getMethods.filter(_.getName.startsWith("copy$default$")).sortBy(
+ _.getName.drop("copy$default$".length).takeWhile(_ != '(').toInt)
val fields = clazz.getDeclaredFields.filterNot(_.getName.startsWith("$"))
if (copyDefaultMethods.length != fields.length)
sys.error("Case class declares additional fields")
@@ -503,8 +506,8 @@ trait ProductFormats {
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)
+ case ex => throw new RuntimeException("Cannot automatically determine case class field names and order " +
+ "for '" + clazz.getName + "', please use the 'jsonFormat' overload with explicit field name specification", ex)
}
}
}
@@ -524,4 +527,4 @@ trait NullOptions extends ProductFormats {
val value = p.productElement(ix).asInstanceOf[T]
(fieldName, writer.write(value)) :: rest
}
-} \ No newline at end of file
+}