norteo
norteo

Reputation: 1848

How to list object key names with jsonpath?

I am using nodejs with jsonpath. I have this json structure:

{
  things:{
    books: [
      {name: "book1"},
      {name: "book2"},
      {name: "book3"},
      {name: "book4"},
    ],
    movies: [
      {name: "movie1"},
      {name: "movie2"},
      {name: "movie3"},
      {name: "movie4"},
    ]
  }
}

I would like to know the jsonpath expression that returns an array with the key names of the things object. That would be:

["books","movies"]

For now, I am doing this:

Object.keys(jsonpath.eval(jsonStructure,"$.things").pop());

But I don't find it elegant... I should not need to get a copy the whole structure when I only need the key names.

Upvotes: 25

Views: 21818

Answers (4)

Suraj Malgave
Suraj Malgave

Reputation: 173

jsonPath has new update jsonpath-plus jsonpath-plus expands on the original specification to add some additional operators and makes explicit some behaviors the original did not spell out.

^ for grabbing the parent of a matching item ~ for grabbing property names of matching items (as array)

so to get proper output use this query things.*~ you can try here also https://jsonpath.com/

Upvotes: 13

Suraj Malgave
Suraj Malgave

Reputation: 173

The syntax you used for give is wrong to get keys in json path use "$.*~" ex. input: { "firstName": "John", "lastName" : "doe", "age" : 26 } output: [ "firstName", "lastName", "age" ]

Upvotes: 0

vincent
vincent

Reputation: 2181

Not exactly what you are asking for, but might still be relevant.

We use object-scan for this kind of task as it is much better suited for data processing and analyzing. Once you wrap your head around it that is (:

Anyways, here is how you could answer your question if you are willing to add another dependency

// const objectScan = require('object-scan');

const data = { things: { books: [ { name: 'book1' }, { name: 'book2' }, { name: 'book3' }, { name: 'book4' } ], movies: [ { name: 'movie1' }, { name: 'movie2' }, { name: 'movie3' }, { name: 'movie4' } ] } };

console.log(objectScan(['things.*'], { rtn: 'property' })(data));
// => [ 'movies', 'books' ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

Disclaimer: I'm the author of object-scan

Upvotes: 1

Retsam
Retsam

Reputation: 33429

I don't believe there is a better solution than your own:

Object.keys(jsonpath.eval(jsonStructure,"$.things").pop());

I think the main misconception here is that you don't have to worry about this snippet "getting a copy of the whole structure", because you aren't copying the whole structure. You already have the entire object loaded into memory, jsonpath doesn't create a new copy, it simply returns a reference to the already existing object, i.e.:

jsonpath.eval(jsonStructure,"$.things").pop() === jsonStructure.things //true

Upvotes: 3

Related Questions