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
Functions for getting, setting, and transforming values at specific JSONPath locations. Includes support for creating intermediate objects (vivification) and applying transformations to multiple matching elements in place.
Get or set the value of the first element matching a JSONPath expression. When setting values, it creates intermediate objects as needed.
/**
* Get or set value of first matching element
* @param {Object} obj - Target object (must be an object)
* @param {string|Array} pathExpression - JSONPath expression string or normalized path array
* @param {*} [newValue] - New value to set (optional, creates intermediate objects/arrays as needed)
* @returns {*} Current value (if getting) or new value (if setting)
*/
function value(obj, pathExpression, newValue);Usage Examples:
const jp = require('jsonpath');
const data = {
store: {
book: [
{ author: "Nigel Rees", price: 8.95 },
{ author: "Evelyn Waugh", price: 12.99 }
]
}
};
// Get first matching value
const firstAuthor = jp.value(data, '$..author');
// Result: "Nigel Rees"
const firstPrice = jp.value(data, '$..price');
// Result: 8.95
// Set existing value
jp.value(data, '$..price', 9.99);
console.log(data.store.book[0].price); // 9.99
// Create new properties (vivification)
const emptyObj = {};
jp.value(emptyObj, '$.store.name', 'My Bookstore');
console.log(emptyObj); // { store: { name: 'My Bookstore' } }
// Create array elements
jp.value(emptyObj, '$.items[0]', 'first item');
jp.value(emptyObj, '$.items[1]', 'second item');
console.log(emptyObj.items); // ['first item', 'second item']
// Set values using complex expressions
jp.value(data, '$..book[?(@.author=="Nigel Rees")].price', 10.50);Get the parent object of the first element matching a JSONPath expression.
/**
* Get parent of first matching element
* @param {Object} obj - Target object (must be an object)
* @param {string} pathExpression - JSONPath expression string
* @returns {*} Parent object of first match
*/
function parent(obj, pathExpression);Usage Examples:
const jp = require('jsonpath');
const data = {
store: {
book: [
{ author: "Nigel Rees", title: "Sayings", price: 8.95 },
{ author: "Evelyn Waugh", title: "Sword", price: 12.99 }
]
}
};
// Get parent of first author
const parentOfAuthor = jp.parent(data, '$..author');
console.log(parentOfAuthor);
// Result: { author: "Nigel Rees", title: "Sayings", price: 8.95 }
// Get parent of a specific book
const parentOfBook = jp.parent(data, '$.store.book[0]');
console.log(parentOfBook);
// Result: [{ author: "Nigel Rees", ... }, { author: "Evelyn Waugh", ... }]
// Get parent of specific property
const parentOfPrice = jp.parent(data, '$.store.book[1].price');
console.log(parentOfPrice);
// Result: { author: "Evelyn Waugh", title: "Sword", price: 12.99 }Apply a transformation function to all elements matching a JSONPath expression, modifying them in place. Returns the modified nodes.
/**
* Apply function to all matching elements, modifying them in place
* @param {Object} obj - Target object (must be an object)
* @param {string} pathExpression - JSONPath expression string
* @param {Function} fn - Transformation function: (value) => newValue
* @returns {Array<Object>} Array of modified node objects with {path: Array, value: any}
*/
function apply(obj, pathExpression, fn);Usage Examples:
const jp = require('jsonpath');
const data = {
store: {
book: [
{ author: "nigel rees", price: 8.95 },
{ author: "evelyn waugh", price: 12.99 }
]
}
};
// Transform all author names to uppercase
const modifiedNodes = jp.apply(data, '$..author', function(value) {
return value.toUpperCase();
});
console.log(modifiedNodes);
// Result: [
// { path: ['$', 'store', 'book', 0, 'author'], value: 'NIGEL REES' },
// { path: ['$', 'store', 'book', 1, 'author'], value: 'EVELYN WAUGH' }
// ]
console.log(data.store.book[0].author); // "NIGEL REES" (modified in place)
// Apply price discount to all books
jp.apply(data, '$..price', function(price) {
return price * 0.9; // 10% discount
});
// Transform arrays (e.g., reverse order)
const arrayData = { numbers: [1, 2, 3], letters: ['a', 'b', 'c'] };
jp.apply(arrayData, '$..*[?(@.length > 1)]', function(array) {
return array.reverse();
});
console.log(arrayData.numbers); // [3, 2, 1]
// Complex transformations using context
jp.apply(data, '$..book[*]', function(book) {
return {
...book,
slug: book.author.toLowerCase().replace(/\s+/g, '-'),
discountedPrice: book.price * 0.8
};
});The value function automatically creates intermediate objects and arrays when setting values on non-existent paths:
const jp = require('jsonpath');
const obj = {};
// Creates nested object structure
jp.value(obj, '$.user.profile.name', 'John');
console.log(obj);
// Result: { user: { profile: { name: 'John' } } }
// Creates array with specific index
jp.value(obj, '$.user.hobbies[0]', 'reading');
jp.value(obj, '$.user.hobbies[2]', 'hiking');
console.log(obj.user.hobbies);
// Result: ['reading', undefined, 'hiking']
// Mixed structures
jp.value(obj, '$.data.items[0].tags[1]', 'important');
console.log(obj.data.items);
// Result: [{ tags: [undefined, 'important'] }]The apply function processes matches from bottom-up (deepest paths first) to handle structural changes safely:
const jp = require('jsonpath');
const data = { a: { b: [1, { c: [2, 3] }] } };
// This works safely even though it modifies structure
jp.apply(data, '$..*[?(@.length > 1)]', function(array) {
return array.reverse();
});
console.log(data);
// Result: { a: { b: [{ c: [3, 2] }, 1] } }All manipulation functions validate their inputs:
AssertionError if obj is not an objectAssertionError if pathExpression is not validAssertionError if fn is not a function (for apply)parent throws error if no matches foundvalue returns undefined if getting non-existent pathapply returns empty array if no matches found