Play [Scala]: How to flatten a JSON object

后端 未结 6 1032
無奈伤痛
無奈伤痛 2021-02-06 13:07

Given the following JSON...

{
  \"metadata\": {
    \"id\": \"1234\",
    \"type\": \"file\",
    \"length\": 395
  }
}

... how do I convert it

6条回答
  •  野趣味
    野趣味 (楼主)
    2021-02-06 13:57

    Here's my take on this problem, based on @Travis Brown's 2nd solution.

    It recursively traverses the json and prefixes each key with its parent's key.

    def flatten(js: JsValue, prefix: String = ""): JsObject = js.as[JsObject].fields.foldLeft(Json.obj()) {
        case (acc, (k, v: JsObject)) => {
            if(prefix.isEmpty) acc.deepMerge(flatten(v, k))
            else acc.deepMerge(flatten(v, s"$prefix.$k"))
        }
        case (acc, (k, v)) => {
            if(prefix.isEmpty) acc + (k -> v)
            else acc + (s"$prefix.$k" -> v)
        }
    }
    

    which turns this:

    {
      "metadata": {
        "id": "1234",
        "type": "file",
        "length": 395
      },
      "foo": "bar",
      "person": {
        "first": "peter",
        "last": "smith",
        "address": {
          "city": "Ottawa",
          "country": "Canada"
        }
      }
    }
    

    into this:

    {
      "metadata.id": "1234",
      "metadata.type": "file",
      "metadata.length": 395,
      "foo": "bar",
      "person.first": "peter",
      "person.last": "smith",
      "person.address.city": "Ottawa",
      "person.address.country": "Canada"
    }
    

提交回复
热议问题