使用json4s在Scala中使用任意嵌套的JSON映射

时间:2015-09-01 07:18:48

标签: scala json4s

我在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)

0 个答案:

没有答案