diff options
author | Michael Bayne <mdb@samskivert.com> | 2012-02-24 15:43:36 -0800 |
---|---|---|
committer | Mathias <mathias@spray.cc> | 2012-02-25 22:22:34 +0100 |
commit | 6f6cae9ad40ef8f6fbdd804443ac2624d6d48467 (patch) | |
tree | 2a70aff6e47642c81d96bb9630ba03d6f3259269 /src/main/scala/cc/spray/json | |
parent | 49e49ee169ff86e4fcbb4f79667cf10788a8bd86 (diff) | |
download | spray-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/main/scala/cc/spray/json')
-rw-r--r-- | src/main/scala/cc/spray/json/ProductFormats.scala | 11 |
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 +} |