Query JavaScript objects with JSONPath expressions using a robust and safe JSONPath engine for Node.js.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Utilities for parsing JSONPath expressions into component objects and converting path arrays back to JSONPath strings. Essential for programmatic manipulation of JSONPath expressions and understanding their structure.
Parse a JSONPath expression string into an array of component objects, revealing the structure and operations of the expression.
/**
* Parse JSONPath expression into component objects
* @param {string} pathExpression - JSONPath expression string (must be a valid string)
* @returns {Array<Object>} Array of path components with structure:
* {expression: {type: string, value: any}, operation?: string, scope?: string}
*/
function parse(pathExpression);Usage Examples:
const jp = require('jsonpath');
// Parse simple path
const components = jp.parse('$.store.book[0].author');
console.log(components);
// Result: [
// { expression: { type: 'root', value: '$' } },
// { expression: { type: 'identifier', value: 'store' }, operation: 'member', scope: 'child' },
// { expression: { type: 'identifier', value: 'book' }, operation: 'member', scope: 'child' },
// { expression: { type: 'numeric_literal', value: 0 }, operation: 'subscript', scope: 'child' },
// { expression: { type: 'identifier', value: 'author' }, operation: 'member', scope: 'child' }
// ]
// Parse recursive descent
const recursiveComponents = jp.parse('$..author');
console.log(recursiveComponents);
// Result: [
// { expression: { type: 'root', value: '$' } },
// { expression: { type: 'identifier', value: 'author' }, operation: 'member', scope: 'descendant' }
// ]
// Parse complex expression with filter
const filterComponents = jp.parse('$..book[?(@.price<10)]');
console.log(filterComponents);
// Shows script expression components with filter details
// Parse array slice
const sliceComponents = jp.parse('$.items[1:3:1]');
// Shows slice operation componentsConvert a path array or parsed component array back to a JSONPath expression string.
/**
* Convert path array or parsed components to JSONPath expression string
* @param {Array|string} path - Flat array of keys, array of parsed path components, or path string
* @returns {string} JSONPath expression string
*/
function stringify(path);Usage Examples:
const jp = require('jsonpath');
// Convert flat path array to JSONPath string
const pathArray = ['$', 'store', 'book', 0, 'author'];
const pathString = jp.stringify(pathArray);
console.log(pathString);
// Result: "$.store.book[0].author"
// Convert parsed components back to string
const components = jp.parse('$..book[*].title');
const reconstructed = jp.stringify(components);
console.log(reconstructed);
// Result: "$..book[*].title"
// Handle various path formats
const simplePath = ['$', 'users', 'john', 'age'];
console.log(jp.stringify(simplePath));
// Result: "$.users.john.age"
const arrayPath = ['$', 'data', 0, 'values', 1];
console.log(jp.stringify(arrayPath));
// Result: "$.data[0].values[1]"
// String literals are properly quoted
const stringPath = ['$', 'store', 'special-key', 'value'];
console.log(jp.stringify(stringPath));
// Result: "$.store['special-key'].value"The parse function returns components with different expression types:
/**
* JSONPath component structure
* @typedef {Object} JSONPathComponent
* @property {Object} expression - The expression object
* @property {string} expression.type - Expression type
* @property {*} expression.value - Expression value
* @property {string} [operation] - Operation type ('member' | 'subscript')
* @property {string} [scope] - Scope type ('child' | 'descendant')
*/
// Expression types:
// - 'root': Root element ($)
// - 'identifier': Property name (e.g., 'book', 'author')
// - 'numeric_literal': Array index (e.g., 0, 1, -1)
// - 'string_literal': Quoted property name (e.g., 'special-key')
// - 'wildcard': Wildcard selector (*)
// - 'slice': Array slice ([start:end:step])
// - 'union': Union selector ([0,1,2])
// - 'filter_expression': Filter expression (?(@.condition))
// - 'script_expression': Script expression ((@.length-1))Components include operation and scope information:
Operations:
'member': Property access (.property)'subscript': Bracket access ([key])Scopes:
'child': Direct child access (. or [...])'descendant': Recursive descent (.. or ..[...])const jp = require('jsonpath');
// Parse, modify, and reconstruct paths
const original = '$.store.book[*].author';
const components = jp.parse(original);
// Change the target property
const lastComponent = components[components.length - 1];
lastComponent.expression.value = 'title';
const modified = jp.stringify(components);
console.log(modified);
// Result: "$.store.book[*].title"
// Build paths programmatically
function buildPath(segments) {
const components = [{ expression: { type: 'root', value: '$' } }];
segments.forEach(segment => {
if (typeof segment === 'string') {
components.push({
expression: { type: 'identifier', value: segment },
operation: 'member',
scope: 'child'
});
} else if (typeof segment === 'number') {
components.push({
expression: { type: 'numeric_literal', value: segment },
operation: 'subscript',
scope: 'child'
});
}
});
return jp.stringify(components);
}
console.log(buildPath(['users', 0, 'profile', 'name']));
// Result: "$.users[0].profile.name"const jp = require('jsonpath');
function analyzePath(pathExpression) {
const components = jp.parse(pathExpression);
const analysis = {
hasRecursiveDescent: components.some(c => c.scope === 'descendant'),
hasWildcards: components.some(c => c.expression.type === 'wildcard'),
hasFilters: components.some(c => c.expression.type === 'filter_expression'),
hasArrayAccess: components.some(c => c.operation === 'subscript'),
depth: components.length - 1 // Exclude root
};
return analysis;
}
console.log(analyzePath('$..book[*].author'));
// Result: { hasRecursiveDescent: true, hasWildcards: true, ... }const jp = require('jsonpath');
const data = { users: [{ name: 'Alice' }, { name: 'Bob' }] };
// Get paths and convert them back to strings
const paths = jp.paths(data, '$..name');
const pathStrings = paths.map(path => jp.stringify(path));
console.log(pathStrings);
// Result: ["$.users[0].name", "$.users[1].name"]
// Use parsed components to understand structure
paths.forEach(path => {
const pathString = jp.stringify(path);
const components = jp.parse(pathString);
console.log(`Path ${pathString} has ${components.length} components`);
});Path processing functions handle various error conditions:
parse throws AssertionError if argument is not a stringparse throws Error for invalid JSONPath syntaxstringify throws AssertionError if no path providedstringify throws Error if it can't find appropriate template for componentstringify throws Error if path format is not recognized