Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
toshi committed Jan 19, 2015
0 parents commit 3da54a9
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
@@ -0,0 +1,6 @@
/RUNNING_PID
/logs/
/project/*-shim.sbt
/project/project/
/project/target/
/target/
12 changes: 12 additions & 0 deletions build.sbt
@@ -0,0 +1,12 @@
name := """play-json-naming"""

version := "1.0"

scalaVersion := "2.11.5"

crossScalaVersions := Seq("2.10.4", "2.11.5")

libraryDependencies ++= Seq(
"com.typesafe.play" %% "play-json" % "2.3.7" % "provided",
"org.scalatest" %% "scalatest" % "2.1.6" % "test"
)
4 changes: 4 additions & 0 deletions project/build.properties
@@ -0,0 +1,4 @@
#Activator-generated Properties
#Mon Jan 19 19:48:42 JST 2015
template.uuid=a855816c-0367-44ba-9adb-6a903f6ad599
sbt.version=0.13.7
25 changes: 25 additions & 0 deletions src/main/scala/com/github/tototoshi/play/json/JsonNaming.scala
@@ -0,0 +1,25 @@
package com.github.tototoshi.play.json

import play.api.libs.json._

object JsonNaming {

private def mapKeys[A, B](m: Seq[(A, B)])(f: A => A): Seq[(A, B)] =
m.map { case (k, v) => (f(k), v) }

def snakecase[T](format: Format[T]): Format[T] = new Format[T] {
def reads(json: JsValue): JsResult[T] = {
format.reads(json match {
case obj: JsObject => JsObject(mapKeys(obj.fields)(StringUtil.camelcase))
case x => x
})
}

def writes(o: T): JsValue = {
format.writes(o) match {
case obj: JsObject => JsObject(mapKeys(obj.fields)(StringUtil.snakecase))
case x => x
}
}
}
}
19 changes: 19 additions & 0 deletions src/main/scala/com/github/tototoshi/play/json/StringUtil.scala
@@ -0,0 +1,19 @@
package com.github.tototoshi.play.json

import play.api.libs.json._

private[json] object StringUtil {

def camelcase(s: String): String = (s.split("_").toList match {
case head :: tail => head :: tail.map(_.capitalize)
case x => x
}).mkString

def snakecase(s: String): String = s.foldLeft(new StringBuilder) {
case (s, c) if Character.isUpperCase(c) =>
s.append("_").append(Character.toLowerCase(c))
case (s, c) =>
s.append(c)
}.toString

}
@@ -0,0 +1,25 @@
package com.github.tototoshi.play.json

import org.scalatest._
import play.api.libs.json._

case class Name(firstName: String, lastName: String)
case class User(id: Int, nameData: Name)

class JsonNamingSuite extends FunSuite with ShouldMatchers {


implicit val nameFormat = JsonNaming.snakecase(Json.format[Name])
implicit val userFormat = JsonNaming.snakecase(Json.format[User])

val jsonString = """{"id":1,"name_data":{"first_name":"Toshiyuki","last_name":"Takahashi"}}"""

test("read") {
Json.parse(jsonString).validate[User].get should be(User(1, Name("Toshiyuki", "Takahashi")))
}

test("write") {
Json.toJson(User(1, Name("Toshiyuki", "Takahashi"))) should be(Json.parse(jsonString))
}

}
@@ -0,0 +1,18 @@
package com.github.tototoshi.play.json

import org.scalatest._
import play.api.libs.json._

class StringUtilSuite extends FunSuite with ShouldMatchers {

test("camelCase -> snake_case") {
StringUtil.snakecase("play") should be("play")
StringUtil.snakecase("playJson") should be("play_json")
}

test("snake_case -> camelCase") {
StringUtil.camelcase("play") should be("play")
StringUtil.camelcase("play_json") should be("playJson")
}

}

0 comments on commit 3da54a9

Please sign in to comment.