From f57e5f96d657c422836f69faf55d8df3992ab3be Mon Sep 17 00:00:00 2001 From: Jakob Odersky Date: Thu, 19 Apr 2018 20:56:27 -0700 Subject: Add utility formats for modifying parameter name extraction --- shared/src/main/scala/DerivedFormats.scala | 2 +- shared/src/main/scala/caseFormats.scala | 47 ++++++++++++++++++++++++++++++ shared/src/test/scala/FieldNameTests.scala | 44 ++-------------------------- 3 files changed, 50 insertions(+), 43 deletions(-) create mode 100644 shared/src/main/scala/caseFormats.scala diff --git a/shared/src/main/scala/DerivedFormats.scala b/shared/src/main/scala/DerivedFormats.scala index 122e744..03e632f 100644 --- a/shared/src/main/scala/DerivedFormats.scala +++ b/shared/src/main/scala/DerivedFormats.scala @@ -11,7 +11,7 @@ trait DerivedFormats { self: BasicFormats => /** Convert the name of a parameter to that of a field in a JSON object. This * method can be overriden to use alternative naming conventions. */ - def extractFieldName(paramName: String): String = paramName + @inline def extractFieldName(paramName: String): String = paramName def combine[T](ctx: CaseClass[JsonFormat, T]): JsonFormat[T] = new JsonFormat[T] { diff --git a/shared/src/main/scala/caseFormats.scala b/shared/src/main/scala/caseFormats.scala new file mode 100644 index 0000000..909e357 --- /dev/null +++ b/shared/src/main/scala/caseFormats.scala @@ -0,0 +1,47 @@ +package spray.json + +/** Serialize parametersOfCaseClasses as parameters_of_case_classes. */ +trait SnakeCase { self: DerivedFormats => + override def extractFieldName(paramName: String) = + FieldNaming.substituteCamel(paramName, '_') +} + +/** Serialize parametersOfCaseClasses as parameters-of-case-classes. */ +trait KebabCase { self: DerivedFormats => + override def extractFieldName(paramName: String) = + FieldNaming.substituteCamel(paramName, '-') +} + +object FieldNaming { + + @inline final private def isLower(ch: Char): Boolean = + ((ch & 0x20) != 0) || (ch == '_') + + @inline final def substituteCamel(paramName: String, substitute: Char) = { + val length = paramName.length + val builder = new StringBuilder(length) + var i = 0 + while (i < length) { + val cur = paramName(i) + val lower = isLower(cur) + if (lower) { + builder.append(cur) + } else { + builder.append((cur ^ 0x20).toChar) + } + if (lower && i + 1 < length) { + val next = paramName(i + 1) + if (!isLower(next)) { + builder.append(substitute) + builder.append((next ^ 0x20).toChar) + } else { + builder.append(next) + } + i += 1 + } + i += 1 + } + builder.result() + } + +} diff --git a/shared/src/test/scala/FieldNameTests.scala b/shared/src/test/scala/FieldNameTests.scala index f1b76a9..885dfb6 100644 --- a/shared/src/test/scala/FieldNameTests.scala +++ b/shared/src/test/scala/FieldNameTests.scala @@ -2,46 +2,6 @@ package spray.json import org.scalatest._ -trait SnakeCaseFormats { self: DerivedFormats => - override def extractFieldName(paramName: String) = - FieldNaming.substituteCamel(paramName, '_') -} -trait KebabCaseFormats { self: DerivedFormats => - override def extractFieldName(paramName: String) = - FieldNaming.substituteCamel(paramName, '-') -} - -object FieldNaming { - - @inline final private def isLower(ch: Char): Boolean = - ((ch & 0x20) != 0) || (ch == '_') - - @inline def substituteCamel(paramName: String, substitute: Char) = { - val length = paramName.length - val builder = new StringBuilder(length) - var i = 0 - while (i < length) { - val cur = paramName(i) - if (isLower(cur) && i + 1 < length) { - builder.append(cur) - val next = paramName(i + 1) - if (!isLower(next)) { - builder.append(substitute) - builder.append((next ^ 0x20).toChar) - } else { - builder.append(next) - } - i += 1 - } else { - builder.append((cur ^ 0x20).toChar) - } - i += 1 - } - builder.result() - } - -} - class FieldNameTests extends FlatSpec with FormatTests { case class A(camelCASE: String, `__a_aB__`: Int, `a-a_B`: Int) @@ -52,7 +12,7 @@ class FieldNameTests extends FlatSpec with FormatTests { } { - object Protocol extends All with SnakeCaseFormats + object Protocol extends All with SnakeCase import Protocol._ "snake_case" should behave like checkRoundtrip( B(A("helloWorld", 0, 0)), @@ -61,7 +21,7 @@ class FieldNameTests extends FlatSpec with FormatTests { } { - object Protocol extends All with KebabCaseFormats + object Protocol extends All with KebabCase import Protocol._ "kebab-case" should behave like checkRoundtrip( B(A("helloWorld", 0, 0)), -- cgit v1.2.3