|
| 1 | +package spray.json |
| 2 | + |
| 3 | +import java.util.Locale |
| 4 | + |
| 5 | +import org.specs2.mutable._ |
| 6 | + |
| 7 | +class SnakeCaseJsonSupportSpec extends Specification with SnakeCaseJsonSupport { |
| 8 | + |
| 9 | + private val PASS1 = """([A-Z]+)([A-Z][a-z])""".r |
| 10 | + private val PASS2 = """([a-z\d])([A-Z])""".r |
| 11 | + private val REPLACEMENT = "$1_$2" |
| 12 | + |
| 13 | + def snakify(name: String) = |
| 14 | + PASS2.replaceAllIn(PASS1.replaceAllIn(name, REPLACEMENT), REPLACEMENT).toLowerCase(Locale.US) |
| 15 | + |
| 16 | + "SnakeCaseJsonSUpport" should { |
| 17 | + "convert field names to snake cased fields names." in { |
| 18 | + // Given |
| 19 | + case class SampleFields( |
| 20 | + HelloWorld: Int = 0, |
| 21 | + A1AAbBBBBBbCCcc: Int = 0, |
| 22 | + AbAAbbAAAbbb1AA2bb1AA2AAAAbb1bAA: Int = 0, |
| 23 | + x: Int = 0, |
| 24 | + Y: Int = 0, |
| 25 | + `^There-arE_Non_(Alphabetic))_character!S`: Int = 0, |
| 26 | + `tHere-Are_(AlsO)_noN_(alphaBetic))_CharaCter!s`: Int = 0, |
| 27 | + ` There are space character `: Int = 0, |
| 28 | + ` これは マルチバイトAbcのaBc確認です。`: Int = 0, |
| 29 | + aa: Int = 0, |
| 30 | + AA: Int = 0, |
| 31 | + Aa: Int = 0, |
| 32 | + aA: Int = 0, |
| 33 | + AAA: Int = 0, |
| 34 | + AAa: Int = 0, |
| 35 | + AaA: Int = 0, |
| 36 | + aAA: Int = 0, |
| 37 | + aaA: Int = 0, |
| 38 | + aAa: Int = 0, |
| 39 | + Aaa: Int = 0, |
| 40 | + aaa: Int = 0 |
| 41 | + ) |
| 42 | + case class SampleFields2( |
| 43 | + aaa123bbb: Int = 0, |
| 44 | + aaA123bbb: Int = 0, |
| 45 | + aaa123Bbb: Int = 0, |
| 46 | + aaA123Bbb: Int = 0, |
| 47 | + aaa123: Int = 0, |
| 48 | + aaA123: Int = 0, |
| 49 | + aAA123: Int = 0 |
| 50 | + ) |
| 51 | + implicit val jsonFormat1: RootJsonFormat[SampleFields] = |
| 52 | + jsonFormat21(SampleFields.apply) |
| 53 | + implicit val jsonFormat2: RootJsonFormat[SampleFields2] = |
| 54 | + jsonFormat7(SampleFields2.apply) |
| 55 | + // When |
| 56 | + val sampleFields1 = SampleFields().toJson.asJsObject |
| 57 | + val sampleFields2 = SampleFields2().toJson.asJsObject |
| 58 | + // Then |
| 59 | + val fields1 = sampleFields1.fields |
| 60 | + fields1.contains(snakify("HelloWorld")) mustEqual true |
| 61 | + fields1.contains(snakify("A1AAbBBBBBbCCcc")) mustEqual true |
| 62 | + fields1.contains(snakify("AbAAbbAAAbbb1AA2bb1AA2AAAAbb1bAA")) mustEqual true |
| 63 | + fields1.contains(snakify("x")) mustEqual true |
| 64 | + fields1.contains(snakify("Y")) mustEqual true |
| 65 | + fields1.contains(snakify("^There-arE_Non_(Alphabetic))_character!S")) mustEqual true |
| 66 | + fields1.contains(snakify("tHere-Are_(AlsO)_noN_(alphaBetic))_CharaCter!s")) mustEqual true |
| 67 | + fields1.contains(snakify(" There are space character ")) mustEqual true |
| 68 | + fields1.contains(snakify(" これは マルチバイトAbcのaBc確認です。")) mustEqual true |
| 69 | + fields1.contains(snakify("aa")) mustEqual true |
| 70 | + fields1.contains(snakify("aA")) mustEqual true |
| 71 | + fields1.contains(snakify("Aa")) mustEqual true |
| 72 | + fields1.contains(snakify("AA")) mustEqual true |
| 73 | + fields1.contains(snakify("AAA")) mustEqual true |
| 74 | + fields1.contains(snakify("aaA")) mustEqual true |
| 75 | + fields1.contains(snakify("aAa")) mustEqual true |
| 76 | + fields1.contains(snakify("Aaa")) mustEqual true |
| 77 | + fields1.contains(snakify("AAa")) mustEqual true |
| 78 | + fields1.contains(snakify("AaA")) mustEqual true |
| 79 | + fields1.contains(snakify("aAA")) mustEqual true |
| 80 | + fields1.contains(snakify("aaa")) mustEqual true |
| 81 | + val fields2 = sampleFields2.fields |
| 82 | + fields2.contains(snakify("aaa123bbb")) mustEqual true |
| 83 | + fields2.contains(snakify("aaa123Bbb")) mustEqual true |
| 84 | + fields2.contains(snakify("aaA123bbb")) mustEqual true |
| 85 | + fields2.contains(snakify("aaa123")) mustEqual true |
| 86 | + fields2.contains(snakify("aaA123")) mustEqual true |
| 87 | + fields2.contains(snakify("aAA123")) mustEqual true |
| 88 | + } |
| 89 | + "deserialize snake cased json" in { |
| 90 | + // Given |
| 91 | + case class SampleFields( |
| 92 | + a: Int, |
| 93 | + aA: Int, |
| 94 | + helloWorld: Int, |
| 95 | + HelloTheWorld: Int |
| 96 | + ) |
| 97 | + implicit val jsonFormat: RootJsonFormat[SampleFields] = |
| 98 | + jsonFormat4(SampleFields.apply) |
| 99 | + val json = JsObject( |
| 100 | + "hello_the_world" -> 4.toJson, |
| 101 | + "a_a" -> 2.toJson, |
| 102 | + "a" -> 1.toJson, |
| 103 | + "hello_world" -> 3.toJson |
| 104 | + ) |
| 105 | + // When |
| 106 | + val result = jsonFormat.read(json) |
| 107 | + // Then |
| 108 | + result mustEqual SampleFields( |
| 109 | + a = 1, aA = 2, helloWorld = 3, HelloTheWorld = 4 |
| 110 | + ) |
| 111 | + } |
| 112 | + } |
| 113 | +} |
0 commit comments