我在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等?
答案 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()