问题
So I have a Map in Scala like this:
val m = Map[String, String](
"a" -> "theA",
"b" -> "theB",
"c" -> "theC",
"d" -> "theD",
"e" -> "theE"
)
and I want to serialize this structure into a JSON string using lift-json.
Do any of you know how to do this?
回答1:
How about this?
implicit val formats = net.liftweb.json.DefaultFormats
import net.liftweb.json.JsonAST._
import net.liftweb.json.Extraction._
import net.liftweb.json.Printer._
val m = Map[String, String](
"a" -> "theA",
"b" -> "theB",
"c" -> "theC",
"d" -> "theD",
"e" -> "theE"
)
println(compact(render(decompose(m))))
output:
{"e":"theE","a":"theA","b":"theB","c":"theC","d":"theD"}
EDIT:
For a scala.collections.mutable.Map
, you should convert it first to an immutable map: .toMap
回答2:
If you are using the latest Scala 2.10.x and above :
println(scala.util.parsing.json.JSONObject(m))
回答3:
You can roll your own pretty easily (yay, no dependencies). This one does basic handling of types and will do recursion unlike JSONObject
that was mentioned:
import scala.collection.mutable.ListBuffer
object JsonConverter {
def toJson(o: Any) : String = {
var json = new ListBuffer[String]()
o match {
case m: Map[_,_] => {
for ( (k,v) <- m ) {
var key = escape(k.asInstanceOf[String])
v match {
case a: Map[_,_] => json += "\"" + key + "\":" + toJson(a)
case a: List[_] => json += "\"" + key + "\":" + toJson(a)
case a: Int => json += "\"" + key + "\":" + a
case a: Boolean => json += "\"" + key + "\":" + a
case a: String => json += "\"" + key + "\":\"" + escape(a) + "\""
case _ => ;
}
}
}
case m: List[_] => {
var list = new ListBuffer[String]()
for ( el <- m ) {
el match {
case a: Map[_,_] => list += toJson(a)
case a: List[_] => list += toJson(a)
case a: Int => list += a.toString()
case a: Boolean => list += a.toString()
case a: String => list += "\"" + escape(a) + "\""
case _ => ;
}
}
return "[" + list.mkString(",") + "]"
}
case _ => ;
}
return "{" + json.mkString(",") + "}"
}
private def escape(s: String) : String = {
return s.replaceAll("\"" , "\\\\\"");
}
}
You can see it in action like
println(JsonConverter.toJson(
Map("a"-> 1,
"b" -> Map(
"nes\"ted" -> "yeah{\"some\":true"),
"c" -> List(
1,
2,
"3",
List(
true,
false,
true,
Map(
"1"->"two",
"3"->"four"
)
)
)
)
)
)
{"a":1,"b":{"nes\"ted":"yeah{\"some\":true"},"c":[1,2,"3",[true,false,true,{"1":"two","3":"four"}]]}
(It's part of a Coinbase GDAX library I've written, see util.scala)
回答4:
You can use this simple way if you are using play framework:
import play.api.libs.json._
Json.toJson(<your_map>)
回答5:
This code will convert many different objects, and doesn't require any libraries beyond the built-in the scala.util.parsing.json._
. It won't properly handle edge cases like Maps with integers as keys.
import scala.util.parsing.json.{JSONArray, JSONObject}
def toJson(arr: List[Any]): JSONArray = {
JSONArray(arr.map {
case (innerMap: Map[String, Any]) => toJson(innerMap)
case (innerArray: List[Any]) => toJson(innerArray)
case (other) => other
})
}
def toJson(map: Map[String, Any]): JSONObject = {
JSONObject(map.map {
case (key, innerMap: Map[String, Any]) =>
(key, toJson(innerMap))
case (key, innerArray: List[Any]) =>
(key, toJson(innerArray))
case (key, other) =>
(key, other)
})
}
回答6:
Similar to Einar's solution, you can use JSONObject from Parser Combinators to do this. Note that it does not recurse, you'll need to do this yourself. The library also includes JSONArray, for list like data structures. Something like the following will address Noel's concerns about nested structures. This example does not recurse to an arbitrary level, but will handle a value of List[Map[String, Any]].
import scala.util.parsing.json.{JSONArray, JSONObject}
def toJson(m : Map[String, Any]): String = JSONObject(
m.mapValues {
case mp: Map[String, Any] => JSONObject(mp)
case lm: List[Map[String, Any]] => JSONArray(lm.map(JSONObject(_)))
case x => x
}
).toString
回答7:
Supplementing the answer by @Raja.
For those nested object, I locally modify the class to have my wanted toString()
like this way:
case class MList[T]() extends MutableList[T] {
override def toString() = "[" + this.toList.mkString(",") + "]"
}
Then inside the Map object, I use this MList
instead of the standard List
. That way, my map
object prints out fine by calling JSONObject(map).toString()
.
来源:https://stackoverflow.com/questions/6271386/how-do-you-serialize-a-map-to-json-in-scala