播放 [Scala]:如何展平 JSON 对象 [英] Play [Scala]: How to flatten a JSON object
问题描述
给定以下 JSON...
Given the following JSON...
{
"metadata": {
"id": "1234",
"type": "file",
"length": 395
}
}
...我如何将其转换为
... how do I convert it to
{
"metadata.id": "1234",
"metadata.type": "file",
"metadata.length": 395
}
发送.
推荐答案
这绝对不是微不足道的,但可以通过尝试递归地将其展平.我还没有彻底测试过,但它适用于您的示例以及我使用数组提出的其他一些基本示例:
This is definitely not trivial, but possible by trying to flatten it recursively. I haven't tested this thoroughly, but it works with your example and some other basic one's I've come up with using arrays:
object JsFlattener {
def apply(js: JsValue): JsValue = flatten(js).foldLeft(JsObject(Nil))(_++_.as[JsObject])
def flatten(js: JsValue, prefix: String = ""): Seq[JsValue] = {
js.as[JsObject].fieldSet.toSeq.flatMap{ case (key, values) =>
values match {
case JsBoolean(x) => Seq(Json.obj(concat(prefix, key) -> x))
case JsNumber(x) => Seq(Json.obj(concat(prefix, key) -> x))
case JsString(x) => Seq(Json.obj(concat(prefix, key) -> x))
case JsArray(seq) => seq.zipWithIndex.flatMap{ case (x, i) => flatten(x, concat(prefix, key + s"[$i]")) }
case x: JsObject => flatten(x, concat(prefix, key))
case _ => Seq(Json.obj(concat(prefix, key) -> JsNull))
}
}
}
def concat(prefix: String, key: String): String = if(prefix.nonEmpty) s"$prefix.$key" else key
}
JsObject
有 fieldSet
方法,它返回一个 Set[(String, JsValue)]
,我映射了它,与 JsValue
子类,并从那里继续递归消费.
JsObject
has the fieldSet
method that returns a Set[(String, JsValue)]
, which I mapped, matched against the JsValue
subclass, and continued consuming recursively from there.
您可以通过将 JsValue
传递给 apply
来使用此示例:
You can use this example by passing a JsValue
to apply
:
val json = Json.parse("""
{
"metadata": {
"id": "1234",
"type": "file",
"length": 395
}
}
"""
JsFlattener(json)
我们将把它留给读者作为练习,以使代码看起来更漂亮.
这篇关于播放 [Scala]:如何展平 JSON 对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!