Home > Enterprise >  get full path up to given element
get full path up to given element

Time:11-02

I have exported bookmarks from Firefox which in my case is quiet large JSON. I'm interested in the object with guid _0no-4e9woLW in a JSON such as this one:

{
  "foo": {
    "bar": {
      "zoo": {
        "guid": "_0no-4e9woLW",
        "title": "frontend",
        "index": 3,
        "dateAdded": 1614198626454000,
        "lastModified": 1619505016472000,
        "id": 16518,
        "typeCode": 2,
        "type": "text/x-moz-place-container",
        "children": [
          {
            "guid": "2L7ZsYTM2RX0",
            "title": "css child override parent style",
            "index": 0,
            "dateAdded": 1614198648005000,
            "lastModified": 1614198648005000,
            "id": 16519,
            "typeCode": 1,
            "type": "text/x-moz-place",
            "uri": "https://www.google.com/search?client=firefox-b-d&q=css child override parent style"
          },
          {
            "guid": "x3JHTAezzyI8",
            "title": "css child parent inheritance",
            "index": 1,
            "dateAdded": 1614198648096000,
            "lastModified": 1614198648096000,
            "id": 16520,
            "typeCode": 1,
            "type": "text/x-moz-place",
            "uri": "https://www.google.com/search?client=firefox-b-d&q=css child parent inheritance"
          }
        ]
      }
    }
  }
}

Is it possible to get somehow full path up to "guid": "_0no-4e9woLW"? guid keys are uniq in JSON. My goal is to type something like jq '["full path I've somehow previously obtained"]["children"].title'

And I will obtain:

css child override parent style
css child parent inheritance

Of course I could do this manually but I'm too lazy.

CodePudding user response:

Without the whole knowledge of the JSON, something like this should work when using path family of functions i.e. getpath/1

( paths | select(.[-1] == "guid") ) as $p | 
  if getpath($p)  == "_0no-4e9woLW" then getpath($p[:-1]   ["children"])[].title else empty end

The construct above means, select all those paths containing the leaf key named guid and store them in a variable and filter only the path whose value turns out to be "_0no-4e9woLW". On the selected path, trim the child node($p[:-1] removes "guid") and add the node "children" and get the value at the new path constructed (using getpath/1). Extract the .title field from the JSON value

jqplay demo

CodePudding user response:

Using recurse allows to get to the object easily :

jq -r 'recurse |
       select(type=="object" and .guid == "_0no-4e9woLW")
       .children[].title' firefox.json

CodePudding user response:

  • To access a node by guid:

    .. | objects | select( .guid == … )
    

    So you'd use the following to get the title of _0no-4e9woLW's children:

    .. | objects | select( .guid == "_0no-4e9woLW" ) | .children[].title
    

    Demo on jqplay

  • To save a path:

    path( … )               # As JSON
    
    path( … ) | join(".")   # As dotted path
    

    Replace with an expression that returns the node(s) for which you want the path.

    For example,

    path( .. | objects | select( .guid == "_0no-4e9woLW" ) )   # [ "foo", "bar", "zoo" ]
    

    Demo on jqplay

    path( .. | objects | select( .guid == "_0no-4e9woLW" ) ) | join(".")   # "foo.bar.zoo"
    

    Demo on jqplay

  • To grab an object using its path:

    getpath( … )                                      # From JSON
    
    getpath( … | split(".") | map(tonumber? // .) )   # From dotted path
    

    Replace with an expression that returns the previously saved path.

    For example,

    getpath( [ "foo", "bar", "zoo" ] ).children[].title
    

    Demo on jqplay

    getpath( "foo.bar.zoo" | split(".") | map(tonumber? // .) ).children[].title
    

    Demo on jqplay

  • Related