Permalink
Browse files

Added support for transforming Map[String, _] or Iterable[Map[String,…

… _]] to a compact JSON string
  • Loading branch information...
1 parent 5ab5690 commit 05024538ecc1f577e623fd862368e1819388e34b @rktoomey rktoomey committed Oct 23, 2012
@@ -36,6 +36,21 @@ import com.novus.salat.StringTypeHintStrategy
import scala.tools.scalap.scalax.rules.scalasig.TypeRefType
import org.bson.types.BSONTimestamp
+object FromMapToJSON extends Logging {
+
+ val empty = compact(render(JObject(Nil)))
+
+ def apply(m: Map[String, _])(implicit ctx: Context): String = compact(render(mapToJObject(m)))
+
+ def mapToJObject(m: Map[String, _])(implicit ctx: Context): JObject = {
+ JObject(m.map(v => ToJField(v._1, v._2)).toList)
+ }
+
+ def apply(iter: Iterable[Map[String, _]])(implicit ctx: Context): String = {
+ compact(render(JArray(iter.map(mapToJObject(_)).toList)))
+ }
+}
+
object ToJField extends Logging {
def typeHint[X](clazz: Class[X], useTypeHint: Boolean)(implicit ctx: Context) = {
val th = if (useTypeHint) {
@@ -57,11 +72,14 @@ object ToJField extends Logging {
object ToJValue extends Logging {
def apply(o: Any)(implicit ctx: Context): JValue = o.asInstanceOf[AnyRef] match {
- case t: MongoDBList => JArray(t.map(apply(_)).toList)
- case t: BasicDBList => JArray(t.map(apply(_)).toList)
- case dbo: DBObject => JObject(wrapDBObj(dbo).toList.map(v => JField(v._1, apply(v._2))))
- case m: Map[_, _] => JObject(m.toList.map(v => JField(v._1.toString, apply(v._2))))
- case x => serialize(x)
+ case t: MongoDBList => JArray(t.map(apply(_)).toList)
+ case t: BasicDBList => JArray(t.map(apply(_)).toList)
+ case dbo: DBObject => JObject(wrapDBObj(dbo).toList.map(v => JField(v._1, apply(v._2))))
+ case m: Map[_, _] => JObject(m.toList.map(v => JField(v._1.toString, apply(v._2))))
+ case m: java.util.Map[_, _] => JObject(scala.collection.JavaConversions.mapAsScalaMap(m).toList.map(v => JField(v._1.toString, apply(v._2))))
+ case iter: Iterable[_] => JArray(iter.map(apply(_)).toList)
+ case iter: java.lang.Iterable[_] => JArray(scala.collection.JavaConversions.iterableAsScalaIterable(iter).map(apply(_)).toList)
+ case x => serialize(x)
}
def serialize(o: Any)(implicit ctx: Context) = {
@@ -0,0 +1,66 @@
+package com.novus.salat.test.json
+
+import com.novus.salat.test.SalatSpec
+import com.novus.salat.json.FromMapToJSON
+import net.liftweb.json._
+
+class JsonMapSupport extends SalatSpec {
+
+ val uglyMap = Map(
+ "text" -> "root", "root" -> true, "depth" -> 0, "children" -> List(
+ Map("children" -> List(
+ Map("text" -> "Orange", "leaf" -> true, "depth" -> 2, "checked" -> true)),
+ "checked" -> true, "expanded" -> true, "text" -> "Orange", "depth" -> 1),
+ Map("children" -> List(
+ Map("text" -> "Acerola", "leaf" -> true, "depth" -> 2, "checked" -> true)),
+ "checked" -> true, "expanded" -> true, "text" -> "Acerola", "depth" -> 1),
+ Map("children" -> List(
+ Map("text" -> "Apple", "leaf" -> true, "depth" -> 2, "checked" -> true),
+ Map("text" -> "Strawberry", "leaf" -> true, "depth" -> 2, "checked" -> true),
+ Map("text" -> "Guava", "leaf" -> true, "depth" -> 2, "checked" -> true),
+ Map("text" -> "Sapote", "leaf" -> true, "depth" -> 2, "checked" -> true),
+ Map("text" -> "Mango", "leaf" -> true, "depth" -> 2, "checked" -> true),
+ Map("text" -> "Limequat", "leaf" -> true, "depth" -> 2, "checked" -> true),
+ Map("text" -> "Langsat", "leaf" -> true, "depth" -> 2, "checked" -> true),
+ Map("text" -> "Papaya", "leaf" -> true, "depth" -> 2, "checked" -> true),
+ Map("text" -> "Cherimoya", "leaf" -> true, "depth" -> 2, "checked" -> true),
+ Map("text" -> "Citron", "leaf" -> true, "depth" -> 2, "checked" -> true),
+ Map("text" -> "Apricot", "leaf" -> true, "depth" -> 2, "checked" -> true),
+ Map("text" -> "Feijoa", "leaf" -> true, "depth" -> 2, "checked" -> true)),
+ "checked" -> true, "expanded" -> true, "text" -> "Calamondin", "depth" -> 1),
+ Map("children" -> List(
+ Map("text" -> "Pear", "leaf" -> true, "depth" -> 2, "checked" -> true),
+ Map("text" -> "Pumpkin", "leaf" -> true, "depth" -> 2, "checked" -> true),
+ Map("text" -> "Pineapple", "leaf" -> true, "depth" -> 2, "checked" -> true),
+ Map("text" -> "Blueberry", "leaf" -> true, "depth" -> 2, "checked" -> true),
+ Map("text" -> "Nance", "leaf" -> true, "depth" -> 2, "checked" -> true)),
+ "checked" -> true, "expanded" -> true, "text" -> "Persimmons", "depth" -> 1)))
+
+ val expected = """{"text":"root","root":true,"depth":0,"children":[{"children":[{"text":"Orange","leaf":true,"depth":2,"checked":true}],"checked":true,"expanded":true,"text":"Orange","depth":1},{"children":[{"text":"Acerola","leaf":true,"depth":2,"checked":true}],"checked":true,"expanded":true,"text":"Acerola","depth":1},{"children":[{"text":"Apple","leaf":true,"depth":2,"checked":true},{"text":"Strawberry","leaf":true,"depth":2,"checked":true},{"text":"Guava","leaf":true,"depth":2,"checked":true},{"text":"Sapote","leaf":true,"depth":2,"checked":true},{"text":"Mango","leaf":true,"depth":2,"checked":true},{"text":"Limequat","leaf":true,"depth":2,"checked":true},{"text":"Langsat","leaf":true,"depth":2,"checked":true},{"text":"Papaya","leaf":true,"depth":2,"checked":true},{"text":"Cherimoya","leaf":true,"depth":2,"checked":true},{"text":"Citron","leaf":true,"depth":2,"checked":true},{"text":"Apricot","leaf":true,"depth":2,"checked":true},{"text":"Feijoa","leaf":true,"depth":2,"checked":true}],"checked":true,"expanded":true,"text":"Calamondin","depth":1},{"children":[{"text":"Pear","leaf":true,"depth":2,"checked":true},{"text":"Pumpkin","leaf":true,"depth":2,"checked":true},{"text":"Pineapple","leaf":true,"depth":2,"checked":true},{"text":"Blueberry","leaf":true,"depth":2,"checked":true},{"text":"Nance","leaf":true,"depth":2,"checked":true}],"checked":true,"expanded":true,"text":"Persimmons","depth":1}]}"""
+
+ "JSON map support" should {
+ "turn a map with simple values into a JSON document" in {
+ val simpleMap = Map("a" -> 1, "b" -> 2.34, "c" -> testDate)
+ FromMapToJSON(simpleMap) must_== """{"a":1,"b":2.34,"c":"2011-12-28T14:37:56.008Z"}"""
+ }
+ "turn a map whose value is a list of simple values into a JSON document" in {
+ val m = Map("a" -> 1, "b" -> 2.34, "c" -> testDate, "d" -> List(1, "x", 3.14, testDate))
+ FromMapToJSON(m) must_== """{"a":1,"b":2.34,"c":"2011-12-28T14:37:56.008Z","d":[1,"x",3.14,"2011-12-28T14:37:56.008Z"]}"""
+ }
+ "turn a map whose value is a list of maps into a JSON document" in {
+ val mm = Map("a" -> 1, "b" -> 2.34, "c" -> testDate)
+ val m = Map("a" -> 1, "b" -> 2.34, "c" -> testDate, "d" -> List(mm, mm, mm))
+ FromMapToJSON(m) must_==
+ """{"a":1,"b":2.34,"c":"2011-12-28T14:37:56.008Z","d":[{"a":1,"b":2.34,"c":"2011-12-28T14:37:56.008Z"},{"a":1,"b":2.34,"c":"2011-12-28T14:37:56.008Z"},{"a":1,"b":2.34,"c":"2011-12-28T14:37:56.008Z"}]}"""
+ }
+ "turn a list of maps into a JSON array" in {
+ val m = Map("a" -> 1, "b" -> 2.34, "c" -> testDate)
+ val l = List(m, m, Map("a" -> 1, "b" -> 2.34, "c" -> testDate, "d" -> List(1, "x", 3.14, testDate)))
+ FromMapToJSON(l) must_==
+ """[{"a":1,"b":2.34,"c":"2011-12-28T14:37:56.008Z"},{"a":1,"b":2.34,"c":"2011-12-28T14:37:56.008Z"},{"a":1,"b":2.34,"c":"2011-12-28T14:37:56.008Z","d":[1,"x",3.14,"2011-12-28T14:37:56.008Z"]}]"""
+ }
+ "deal with ugly nested maps" in {
+ FromMapToJSON(uglyMap) must_== expected
+ }
+ }
+}

0 comments on commit 0502453

Please sign in to comment.