Config readers, GraphQL resolvers, and tools like jq all need to pull a value out of deeply nested data by a path — user.roles[0], items[*].price. A small query engine turns that string into a walk through the object. The twist over a plain obj.a.b.c lookup is the wildcard *: it doesn't pick one child, it picks all of them, so a single path can produce many results. That's why the answer is always an array.
Implement jsonPathQuery(data, path) supporting dotted keys, array indices (bracket or dotted), and *. See JSONPath for the fuller syntax this simplifies.
function jsonPathQuery(data, path) {
// returns an array of every value matching `path`
}
const data = { users: [{ name: 'A' }, { name: 'B' }], config: { a: 1, b: 2 } };
jsonPathQuery(data, 'users[0].name'); // ['A']
jsonPathQuery(data, 'users[*].name'); // ['A', 'B'] — wildcard fans out
jsonPathQuery(data, 'config.*'); // [1, 2]
jsonPathQuery(data, 'users[9].name'); // [] — out of range
., and treat [n]/[*] the same as .n/.*. An optional leading $ (root) is ignored.* expands to every array element or every object value at that level, so downstream segments run against each.[] for no match.Unlock the solution & editor
Runnable editor + tests
Solve in the browser with instant Jest feedback.
Detailed solutions
Walkthroughs, edge cases, and complexity notes.
Multi-framework variants
React, Vue, Vanilla, Angular — same question, different stacks.