Search code examples
jsonpathnestedkeyjq

Use jq to get all parent keys of specific key


What I want to do is 'walk' on my json, and for each key named 'base', add a key which is the full 'path' of this key.

This is my JSON:

{
  "entity": {
    "product": {
      "att": {
        "number_of_values": "Number of values"
      },
      "title": {
        "base": ["product", "products", "pdt", "pdts"]
      }
    },
    "rabbit": {
      "att": {
        "number_of_values": "Number of values"
      },
      "title": {
        "base": ["rabbit", "rabbits"]
      }
    }
  }
}

And I want a result like this :

{
  "entity": {
    "product": {
      "att": {
        "number_of_values": "Number of values"
      },
      "title": {
        "base": ["product", "products", "pdt", "pdts"],
        "path": "entity.product.title"
      }
    },
    "rabbit": {
      "att": {
        "number_of_values": "Number of values"
      },
      "title": {
        "base": ["rabbit", "rabbits"]
        "path": "entity.rabbit.title"
      }
    }
  }
}

Actually, I achieve this, but I get only one sub key:

walk(if type == "object" and .base then  keys[] as $k | .base |= {path: $k} else . end)

Results:

{
  "entity": {
    "product": {
      "att": {
        "number_of_values": "Number of values"
      },
      "title": {
        "base": {
          "path": "base"
        }
      }
    },
    "rabbit": {
      "att": {
        "number_of_values": "Number of values"
      },
      "title": {
        "base": {
          "path": "base"
        }
      }
    }
  }
}

I also tried this:

walk(if type == "object" and .base then  paths(..) as $v | .base |= {path: $v} else . end)

Results:

{
  "entity": {
    "product": {
      "att": {
        "number_of_values": "Number of values"
      },
      "title": {
        "base": {
          "path": [
            "base",
            3
          ]
        }
      }
    },
    "rabbit": {
      "att": {
        "number_of_values": "Number of values"
      },
      "title": {
        "base": {
          "path": [
            "base",
            1
          ]
        }
      }
    }
  }
}

Your advice and expertise is greatly appreciated!


Solution

  • Here is one way:

    reduce paths(objects | has("base")) as $p (.;
      setpath($p + ["path"]; $p | join("."))
    )
    

    Online demo