如何在scala中解析JsArary?

时间:2017-11-08 13:47:38

标签: json scala playframework

我在Scala中的JsArray(或String)中遵循JSON。

[
  {
    "row1": [
      {
        "seatId": "R1",
        "seatStatus": "BOOKED",
        "seatIsLadies": false
      },
      {
        "seatId": "R3",
        "seatStatus": "AVAILABLE",
        "seatIsLadies": false
      }
    ]
  },
  {
    "row2": [
      {
        "seatId": "R1",
        "seatStatus": "BOOKED",
        "seatIsLadies": false
      },
      {
        "seatId": "R3",
        "seatStatus": "AVAILABLE",
        "seatIsLadies": false
      }
    ]
  },
  {
    "row3": [
      {
        "seatId": "R1",
        "seatStatus": "BOOKED",
        "seatIsLadies": false
      },
      {
        "seatId": "R3",
        "seatStatus": "AVAILABLE",
        "seatIsLadies": false
      },
      {
        "seatId": "R3",
        "seatStatus": "AVAILABLE",
        "seatIsLadies": false
      }
    ]
  }
]

其中row1,row2,row3可以根据调用而变化,有时它可以是row1-5或者row1-4。我该如何解析这个JSON?如何提取row1,row2等?

2 个答案:

答案 0 :(得分:3)

我的想法是将数组解析为Vector[JsObject],然后使用任何键(row1,row2,row3,...)作为案例类Row中的字段并解析内部数组为Vector个席位。

对于以下代码,请注意我没有错误处理!您不希望仅使用.as方法,而是使用例如validate,并且在构建.head类时,同样适用于不安全的Row调用。话虽如此,

这是一个完全相同的菊石脚本:

import $ivy.`com.typesafe.play::play-json:2.6.7`

import play.api.libs.json._

case class Row(name: String, seats: Vector[Seat])

case class Seat(seatId: String, seatStatus: String, seatIsLadies: Boolean)

object Seat {
  implicit def format: Format[Seat] = Json.format[Seat]
}

  val inputJson = """
[
  {
    "row1": [
      {
        "seatId": "R1",
        "seatStatus": "BOOKED",
        "seatIsLadies": false
      },
      {
        "seatId": "R3",
        "seatStatus": "AVAILABLE",
        "seatIsLadies": false
      }
    ]
  },
  {
    "row2": [
      {
        "seatId": "R1",
        "seatStatus": "BOOKED",
        "seatIsLadies": false
      },
      {
        "seatId": "R3",
        "seatStatus": "AVAILABLE",
        "seatIsLadies": false
      }
    ]
  },
  {
    "row3": [
      {
        "seatId": "R1",
        "seatStatus": "BOOKED",
        "seatIsLadies": false
      },
      {
        "seatId": "R3",
        "seatStatus": "AVAILABLE",
        "seatIsLadies": false
      },
      {
        "seatId": "R3",
        "seatStatus": "AVAILABLE",
        "seatIsLadies": false
      }
    ]
  }
]
"""

val json = Json.parse(inputJson)

val rowObjs = json.as[Vector[JsObject]]

val result = rowObjs.map(obj => Row(obj.fields.head._1, obj.fields.head._2.as[Vector[Seat]]))

println(result)

导致输出结果:

Vector(
  Row(row1,Vector(Seat(R1,BOOKED,false), Seat(R3,AVAILABLE,false))), 
  Row(row2,Vector(Seat(R1,BOOKED,false), Seat(R3,AVAILABLE,false))), 
  Row(row3,Vector(Seat(R1,BOOKED,false), Seat(R3,AVAILABLE,false),Seat(R3,AVAILABLE,false)))
)

答案 1 :(得分:1)

您可以使用recursive path operator \\

import play.api.libs.json._

case class RowValue(seatId: String, seatStatus: String, seatIsLadies: Boolean)
object RowValue {
  implicit val rowFormat: Format[RowValue] = Json.using[Json.WithDefaultValues].format[RowValue]
}
// in json is your json string
val js: JsValue = Json.parse(json)
val rowNames: Seq[String] = Seq[String]("row1", "row2", "row3", "row4", "row5")
rowNames.foreach { r =>
  val rowValues = (js \\ r).map(x => x.asOpt[Seq[RowValue]])
  println(s"$r => $rowValues")
}

输出将是:

row1 => ArrayBuffer(Some(List(RowValue(R1,BOOKED,false), RowValue(R3,AVAILABLE,false))))
row2 => ArrayBuffer(Some(List(RowValue(R1,BOOKED,false), RowValue(R3,AVAILABLE,false))))
row3 => ArrayBuffer(Some(List(RowValue(R1,BOOKED,false), RowValue(R3,AVAILABLE,false), RowValue(R3,AVAILABLE,false))))
row4 => ArrayBuffer()
row5 => ArrayBuffer()