だから私はScalaにこのようにマップを持っています:
val m = Map[String, String](
"a" -> "theA",
"b" -> "theB",
"c" -> "theC",
"d" -> "theD",
"e" -> "theE"
)
そして、私はlift-jsonを使用してこの構造をJSON文字列にシリアル化したいと思います。
これを行う方法を知っている人はいますか?
これはどう?
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))))
出力:
{"e":"theE","a":"theA","b":"theB","c":"theC","d":"theD"}
編集:
のために scala.collections.mutable.Map
、まず不変のマップに変換する必要があります:.toMap
最新のScala 2.10.x以降を使用している場合:
println(scala.util.parsing.json.JSONObject(m))
あなたはかなり簡単にあなた自身のものを転がすことができます(そう、依存関係はありません)。これはタイプの基本的な処理を行い、前述の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("\"" , "\\\\\"");
}
}
あなたはそれのような行動でそれを見ることができます
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"}]]}
(これは私が作成したCoinbase GDAXライブラリの一部です。 til.scala を参照してください)
Playフレームワークを使用している場合は、この簡単な方法を使用できます。
import play.api.libs.json._
Json.toJson(<your_map>)
このコードは多くの異なるオブジェクトを変換し、組み込みのscala.util.parsing.json._
以外のライブラリを必要としません。整数をキーとするマップのようなEdgeケースを適切に処理しません。
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)
})
}
Einarのソリューションと同様に、 Parser Combinators の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
@Rajaによる回答の補足。
これらのネストされたオブジェクトの場合、次のようにクラスをローカルに変更して、必要なtoString()
を作成します。
case class MList[T]() extends MutableList[T] { override def toString() = "[" + this.toList.mkString(",") + "]" }
次に、Mapオブジェクト内で、標準のMList
ではなく、このList
を使用します。このようにして、map
オブジェクトはJSONObject(map).toString()
を呼び出して正常に出力されます。