diff options
author | Mathias <mathias@spray.io> | 2014-10-28 13:23:35 +0100 |
---|---|---|
committer | Mathias <mathias@spray.io> | 2014-10-28 13:23:35 +0100 |
commit | ef6d8a21849a97cdfc63c5cb740dd55f24807a48 (patch) | |
tree | f5a6970b0643d9fe2846b444c96d194476969654 | |
parent | c3bd8fe437f422e1314a1a2ecd45c1d8f16facaa (diff) | |
download | spray-json-ef6d8a21849a97cdfc63c5cb740dd55f24807a48.tar.gz spray-json-ef6d8a21849a97cdfc63c5cb740dd55f24807a48.tar.bz2 spray-json-ef6d8a21849a97cdfc63c5cb740dd55f24807a48.zip |
Add member name unmangling to ProductFormats, fixes #120
-rw-r--r-- | src/main/scala/spray/json/ProductFormats.scala | 27 | ||||
-rw-r--r-- | src/test/scala/spray/json/ProductFormatsSpec.scala | 13 |
2 files changed, 39 insertions, 1 deletions
diff --git a/src/main/scala/spray/json/ProductFormats.scala b/src/main/scala/spray/json/ProductFormats.scala index 5f5a9f4..39d5300 100644 --- a/src/main/scala/spray/json/ProductFormats.scala +++ b/src/main/scala/spray/json/ProductFormats.scala @@ -78,12 +78,37 @@ trait ProductFormats extends ProductFormatsInstances { sys.error("Case class " + clazz.getName + " declares additional fields") if (fields.zip(copyDefaultMethods).exists { case (f, m) => f.getType != m.getReturnType }) sys.error("Cannot determine field order of case class " + clazz.getName) - fields.map(_.getName) + fields.map(f => ProductFormats.unmangle(f.getName)) } catch { case NonFatal(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) } } + +} + +object ProductFormats { + private val operators = Map( + "$eq" -> "=", + "$greater" -> ">", + "$less" -> "<", + "$plus" -> "+", + "$minus" -> "-", + "$times" -> "*", + "$div" -> "/", + "$bang" -> "!", + "$at" -> "@", + "$hash" -> "#", + "$percent" -> "%", + "$up" -> "^", + "$amp" -> "&", + "$tilde" -> "~", + "$qmark" -> "?", + "$bar" -> "|") + + private def unmangle(name: String) = operators.foldLeft(name) { case (n, (mangled, unmangled)) => + if (n.indexOf(mangled) >= 0) n.replace(mangled, unmangled) else n + } } /** diff --git a/src/test/scala/spray/json/ProductFormatsSpec.scala b/src/test/scala/spray/json/ProductFormatsSpec.scala index c4bb489..a290604 100644 --- a/src/test/scala/spray/json/ProductFormatsSpec.scala +++ b/src/test/scala/spray/json/ProductFormatsSpec.scala @@ -28,6 +28,7 @@ class ProductFormatsSpec extends Specification { } @SerialVersionUID(1L) // SerialVersionUID adds a static field to the case class case class TestStatic(a: Int, b: Option[Double]) + case class TestMangled(`foo-bar!`: Int) trait TestProtocol { this: DefaultJsonProtocol => @@ -36,6 +37,7 @@ class ProductFormatsSpec extends Specification { implicit def test3Format[A: JsonFormat, B: JsonFormat] = jsonFormat2(Test3.apply[A, B]) implicit def testTransientFormat = jsonFormat2(TestTransient) implicit def testStaticFormat = jsonFormat2(TestStatic) + implicit def testMangledFormat = jsonFormat1(TestMangled) } object TestProtocol1 extends DefaultJsonProtocol with TestProtocol object TestProtocol2 extends DefaultJsonProtocol with TestProtocol with NullOptions @@ -181,4 +183,15 @@ class ProductFormatsSpec extends Specification { JsNull.convertTo[Test0] must throwA(new DeserializationException("Object expected")) ) } + + "A JsonFormat created with `jsonFormat`, for a case class with mangled-name members," should { + import TestProtocol1._ + val json = "{\"foo-bar!\":42}" + "produce the correct JSON" in { + TestMangled(42).toJson.compactPrint === json + } + "convert a JsObject to the respective case class instance" in { + json.parseJson.convertTo[TestMangled] === TestMangled(42) + } + } } |