[英]JsLookup on multiple level array using play Json library (or any other suggestion)
My function is receiving a JsValue
, now this json have lists, and this lists element could also be lists, for example:我的函数正在接收一个
JsValue
,现在这个 json 有列表,这个列表元素也可以是列表,例如:
{
"firstName": "Elon",
"lastName": "Musk",
"companies": [
{
"name": "Tesla",
"city": "San Francisco",
"offices": ["sf", "ny"],
"management": {
"loscation": "New York",
"boardMembers": [
{
"name": "John",
"age": 45
},
{
"name": "Mike",
"age": 55
},
{
"name": "Rebecca",
"age": 35
}
]
}
},
{
"name": "SpaceX",
"city": "San Francisco",
"offices": ["la", "ta"],
"management": {
"loscation": "San Mateo",
"boardMembers": [
{
"name": "Lisa",
"age": 45
},
{
"name": "Dan",
"age": 55
},
{
"name": "Henry",
"age": 35
}
]
}
}
]
}
So a company have management object, which have boardMembers list.所以一个公司有管理对象,其中有 boardMembers 列表。
My function is receiving the path to this element, for example:我的函数正在接收该元素的路径,例如:
companies[*].management.boardMembers[*].name
I want it to return a list with all the elements of this object, so the result will be:我希望它返回一个包含此对象所有元素的列表,因此结果将是:
["John", "Mike", "Rebecca", "Lisa", "Dan", "Henry"]
It's a bit complicated, but I thought maybe play.api.libs.json._
would have some feature that could help.这有点复杂,但我认为
play.api.libs.json._
可能会有一些play.api.libs.json._
功能。
thought about splitting it pathStr.split("(\\\\[\\\\*]\\\\.|\\\\[\\\\*])").toList
and then iterate to get all elements some how and return JsLookupResult but not sure how.考虑拆分它
pathStr.split("(\\\\[\\\\*]\\\\.|\\\\[\\\\*])").toList
然后迭代以获取所有元素的一些方法并返回 JsLookupResult 但不确定如何。
Just to clarify:只是为了澄清:
My method will receive 2 parameters, the JsValue
and the path as string def myFunc(json: JsValue, path: String)
我的方法将接收 2 个参数,
JsValue
和作为字符串的路径def myFunc(json: JsValue, path: String)
every time I call myFunc
it can receive different path, I'm not sure what it will be only after myFunc
was called.每次我调用
myFunc
它都会收到不同的路径,我不确定只有在调用myFunc
之后它会是什么。
As you can see in the documentation, you can use the Reads
typeclass to define the way to decode types from JSON.正如您在文档中所见,您可以使用
Reads
类型类来定义从 JSON 解码类型的方式。
import play.api.libs.json._
val input = """{
"firstName": "Elon",
"lastName": "Musk",
"companies": [
{
"name": "Tesla",
"city": "San Francisco",
"offices": ["sf","ny"],
"management": {
"loscation": "New York",
"boardMembers": [
{
"name": "John",
"age": 45
},
{
"name": "Mike",
"age": 55
},
{
"name": "Rebecca",
"age": 35
}
]
}
},
{
"name": "SpaceX",
"city": "San Francisco",
"offices": ["la","ta"],
"management": {
"loscation": "San Mateo",
"boardMembers": [
{
"name": "Lisa",
"age": 45
},
{
"name": "Dan",
"age": 55
},
{
"name": "Henry",
"age": 35
}
]
}
}
]
}"""
val json = Json.parse(input)
// ---
case class BoardMember(name: String, age: Int)
implicit val br: Reads[BoardMember] = Json.reads
case class Company(boardMembers: Seq[BoardMember])
implicit val cr: Reads[Company] = Reads {
case obj @ JsObject(_) =>
(obj \ "management" \ "boardMembers").validate[Seq[BoardMember]].map {
Company(_)
}
case _ =>
JsError("error.obj.expected")
}
val reads = Reads[Seq[String]] {
case obj @ JsObject(_) =>
(obj \ "companies").validate[Seq[Company]].map {
_.flatMap(_.boardMembers.map(_.name))
}
case _ =>
JsError("error.obj.expected")
}
// ---
json.validate(reads)
// play.api.libs.json.JsResult[Seq[String]] = JsSuccess(Vector(John, Mike, Rebecca, Lisa, Dan, Henry),)
You can do:你可以做:
val jsPath = JsPath \ "companies" \\ "management" \ "boardMembers" \\ "name"
val result = jsPath(Json.parse(input))
println(result)
Which will print the expected output.这将打印预期的输出。 See Scastie example.
参见Scastie示例。
Please note the difference between \\
and \\\\
:请注意
\\
和\\\\
之间的区别:
To implement myFunc
you can try something like this:要实现
myFunc
您可以尝试以下操作:
def findAllValuesAtPath(jsValue: JsValue, path: String): List[JsValue] = {
val jsPath = JsPath(path
.split("\\[\\*]\\.")
.flatMap(s => s.split("\\.")
.map(RecursiveSearch)
).toList)
println(jsPath.path)
jsPath(jsValue)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.