如何在 Scala 中将 Map 序列化为 JSON?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6271386/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you serialize a Map to JSON in Scala?
提问by Jay Taylor
So I have a Map in Scala like this:
所以我在 Scala 中有一个像这样的地图:
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.
我想使用lift-json将此结构序列化为JSON字符串。
Do any of you know how to do this?
你们中有人知道如何做到这一点吗?
回答by Raja
If you are using the latest Scala 2.10.x and above :
如果您使用的是最新的 Scala 2.10.x 及更高版本:
println(scala.util.parsing.json.JSONObject(m))
回答by Raja
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
对于 a scala.collections.mutable.Map,您应该先将其转换为不可变映射:.toMap
回答by jar
You can roll your own pretty easily (yay, no dependencies). This one does basic handling of types and will do recursion unlike JSONObjectthat was mentioned:
你可以很容易地推出你自己的(是的,没有依赖关系)。这个做类型的基本处理,并且会做递归,不像JSONObject提到的那样:
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)
(它是我编写的 Coinbase GDAX 库的一部分,请参阅util.scala)
回答by Haimei
You can use this simple way if you are using play framework:
如果您使用的是播放框架,则可以使用这种简单的方法:
import play.api.libs.json._
Json.toJson(<your_map>)
回答by robert
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.
此代码将转换许多不同的对象,并且除了内置的scala.util.parsing.json._. 它不会正确处理边缘情况,例如以整数为键的 Maps。
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)
})
}
回答by Junji Shimagaki
Supplementing the answer by @Raja.
补充@Raja的答案。
For those nested object, I locally modify the class to have my wanted toString()like this way:
对于那些嵌套对象,我在本地修改类,以toString()这样方式获得我想要的:
case class MList[T]() extends MutableList[T] {
override def toString() = "[" + this.toList.mkString(",") + "]"
}
case class MList[T]() extends MutableList[T] {
override def toString() = "[" + this.toList.mkString(",") + "]"
}
Then inside the Map object, I use this MListinstead of the standard List. That way, my mapobject prints out fine by calling JSONObject(map).toString().
然后在 Map 对象中,我使用 thisMList而不是标准的List. 这样,我的map对象通过调用JSONObject(map).toString().
回答by jwhitlark
Similar to Einar's solution, you can use JSONObject from Parser Combinatorsto 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]].
与 Einar 的解决方案类似,您可以使用Parser Combinator 中的JSONObject来执行此操作。请注意,它不会递归,您需要自己执行此操作。该库还包括 JSONArray,用于类似数据结构的列表。类似下面的内容将解决 Noel 对嵌套结构的担忧。此示例不会递归到任意级别,但会处理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

