我在Scala中使用json4s。现在,给出以下JSON:
{
'k1': [
{"a" : "hello1", "b": "city1" },
{"a" : "hello2", "b": "city2" },
{"a" : "hello2", "b": "city2" }
],
'k2': [
{"a" : "hello1", "b": "city1" },
{"a" : "hello2", "b": "city2" },
{"a" : "hello2", "b": "city2" }
]
}
在Scala中将其转换为单级Map的最短方法是什么:
Map(
"k1.$[0].a" => "hello1",
"k1.$[0].b" => "city1",
"k1.$[1].a" => "hello2",
"k1.$[1].b" => "city2",
"k1.$[2].a" => "hello2",
"k1.$[2].b" => "city2",
"k2.$[0].a" => "hello1",
"k2.$[0].b" => "city1",
"k2.$[1].a" => "hello2",
"k2.$[1].b" => "city2",
"k2.$[2].a" => "hello2",
"k2.$[2].b" => "city2"
)
请注意,顶级JSON始终是Object,而不是数组{}
而不是[]
。它也可以嵌入深层,没有预先知道的限制。
EDIT1
好吧,这就是我目前正在做的事情:
import org.json4s._
import org.json4s.native.JsonMethods._
object Experiments {
def toMap(json: JValue, prefix: String = ""): Map[String, Any] = {
json match {
case obj: JObject =>
obj.values flatMap {
case (k, v) =>
toMap(v.asInstanceOf[JValue], prefix + s".$k")
}
case arr: JArray =>
val returnValues = arr.values.zipWithIndex flatMap {
case (v, index) =>
toMap(v.asInstanceOf[JValue], prefix + s".$$[$index]")
}
returnValues.toMap
case value: JBool =>
Map(prefix -> value)
case value: JDecimal =>
Map(prefix -> value)
case value: JDouble =>
Map(prefix -> value)
case value: JInt =>
Map(prefix -> value)
case value: JString =>
Map(prefix -> value)
case JNothing | JNull =>
Map(prefix -> JNull)
}
}
def main(args: Array[String]) {
val json2 = parse( """ {"a": {"b": "c"}} """)
print(toMap(json2))
}
}
它不起作用,我收到此错误:
Exception in thread "main" java.lang.ClassCastException: scala.collection.immutable.Map$Map1 cannot be cast to org.json4s.JsonAST$JValue
at Experiments$$anonfun$toMap$1.apply(Experiments.scala:10)
at Experiments$$anonfun$toMap$1.apply(Experiments.scala:8)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:252)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:252)
at scala.collection.immutable.Map$Map1.foreach(Map.scala:116)
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:252)
at scala.collection.AbstractTraversable.flatMap(Traversable.scala:104)
at Experiments$.toMap(Experiments.scala:8)
at Experiments$.main(Experiments.scala:35)
at Experiments.main(Experiments.scala)
EDIT2
以下代码适用于我:
import org.json4s._
import org.json4s.native.JsonMethods._
object Experiments {
def toMap(v: Any, prefix: String = "", separator: String = "/"): Map[String, Any] = {
v match {
case m: Map[_, _] =>
m.flatMap { case (k, v) =>
toMap(v, prefix + s"$separator$k")
}
case list: List[_] =>
val returnValues = list.zipWithIndex flatMap {
case (v, index) =>
toMap(v, prefix + s"$separator$$[$index]")
}
returnValues.toMap
case _ =>
Map(prefix -> v)
}
}
def main(args: Array[String]) {
val s1 = """ {"a": {"b": "c"}} """
val s2 =
"""
{
"k1": [ {"a" : "hello1", "b": "city1" }, {"a" : "hello2", "b": "city2" }, {"a" : "hello2", "b": "city2" } ] ,
"k2": [ {"a" : "hello1", "b": "city1" }, {"a" : "hello2", "b": "city2" }, {"a" : "hello2", "b": "city2" } ]
}
"""
for (s <- List(s1, s2)) {
println(s"JSON string: $s")
val json2 = parse(s)
val flatm = toMap(json2.values)
flatm foreach println
println()
}
}
}
OUTPUT2
JSON string: {"a": {"b": "c"}}
(/a/b,c)
JSON string:
{
"k1": [ {"a" : "hello1", "b": "city1" }, {"a" : "hello2", "b": "city2" }, {"a" : "hello2", "b": "city2" } ] ,
"k2": [ {"a" : "hello1", "b": "city1" }, {"a" : "hello2", "b": "city2" }, {"a" : "hello2", "b": "city2" } ]
}
(/k1/$[2]/a,hello2)
(/k2/$[0]/a,hello1)
(/k1/$[2]/b,city2)
(/k1/$[1]/a,hello2)
(/k2/$[1]/a,hello2)
(/k1/$[1]/b,city2)
(/k2/$[2]/a,hello2)
(/k2/$[0]/b,city1)
(/k1/$[0]/a,hello1)
(/k2/$[1]/b,city2)
(/k2/$[2]/b,city2)
(/k1/$[0]/b,city1)