Path Utilities
Utility functions for working with JSONPath strings and JSON Pointers. Learn how to parse, convert, normalize, and manipulate path expressions programmatically.
Overview
jsonpathx provides utility functions for path manipulation, conversion between path formats, and programmatic path construction.
import { PathUtils } from '@jsonpathx/jsonpathx';Path Formats
JSONPath Format
Standard JSONPath expression format:
$.store.books[0].titleJSON Pointer Format
RFC 6901 JSON Pointer format:
/store/books/0/titleNormalized Path Format
Canonical bracket notation:
$['store']['books'][0]['title']Core Functions
toPointer()
Convert JSONPath expression to JSON Pointer.
import { PathUtils } from '@jsonpathx/jsonpathx';
const path = '$.store.books[0].title';
const pointer = PathUtils.toPointer(path);
console.log(pointer); // '/store/books/0/title'Edge Cases:
// Root
PathUtils.toPointer('$'); // ''
// Array indices
PathUtils.toPointer('$.items[5]'); // '/items/5'
// Special characters
PathUtils.toPointer('$.items["special/char"]'); // '/items/special~1char'
// Wildcard (not convertible)
PathUtils.toPointer('$.items[*]'); // Error: Wildcards not supportedfromPointer()
Convert JSON Pointer to JSONPath expression.
const pointer = '/store/books/0/title';
const path = PathUtils.fromPointer(pointer);
console.log(path); // '$.store.books[0].title'Edge Cases:
// Root
PathUtils.fromPointer(''); // '$'
// Escaped characters
PathUtils.fromPointer('/items/special~1char'); // '$.items["special/char"]'fromPointerArray()
Convert JSON Pointer to a path array.
const array = PathUtils.fromPointerArray('/store/books/0/title');
console.log(array); // ['$', 'store', 'books', 0, 'title']normalize()
Convert JSONPath to normalized bracket notation.
// Dot notation to bracket notation
const normalized = PathUtils.normalize('$.user.name');
console.log(normalized); // "$['user']['name']"
// Mixed notation
const mixed = PathUtils.normalize('$.store.books[0].title');
console.log(mixed); // "$['store']['books'][0]['title']"Benefits:
- Consistent format
- Handles special characters
- Easier to parse programmatically
parse()
Parse JSONPath expression into components.
const components = PathUtils.parse('$.store.books[0].title');
console.log(components);
// [
// { type: 'root', value: '$' },
// { type: 'property', value: 'store' },
// { type: 'property', value: 'books' },
// { type: 'index', value: 0 },
// { type: 'property', value: 'title' }
// ]Component Types:
root- Root identifier ($)property- Object propertyindex- Array indexwildcard- Wildcard selector (*)slice- Array slicefilter- Filter expressionrecursive- Recursive descent (..)
stringify()
Build JSONPath expression from components.
const components = [
{ type: 'root', value: '$' },
{ type: 'property', value: 'store' },
{ type: 'index', value: 0 }
];
const path = PathUtils.stringify(components);
console.log(path); // '$.store[0]'Path Construction
build()
Programmatically build JSONPath expressions.
// Simple path
const path1 = PathUtils.build(['store', 'books', 0, 'title']);
console.log(path1); // '$.store.books[0].title'
// With special characters
const path2 = PathUtils.build(['users', 'first name', 'email']);
console.log(path2); // '$["users"]["first name"]["email"]'
// With wildcards
const path3 = PathUtils.build(['items', '*', 'price']);
console.log(path3); // '$.items[*].price'append()
Append segments to existing path.
const base = '$.store.books';
const extended = PathUtils.append(base, '[0]', '.title');
console.log(extended); // '$.store.books[0].title'parent()
Get parent path.
const path = '$.store.books[0].title';
const parentPath = PathUtils.parent(path);
console.log(parentPath); // '$.store.books[0]'
// Multiple levels
const grandparent = PathUtils.parent(parentPath);
console.log(grandparent); // '$.store.books'
// Root has no parent
const rootParent = PathUtils.parent('$');
console.log(rootParent); // nullPath Validation
isValid()
Check if path is valid JSONPath syntax.
PathUtils.isValid('$.store.books'); // true
PathUtils.isValid('$.items[*]'); // true
PathUtils.isValid('$.users[0:10]'); // true
PathUtils.isValid('store.books'); // false (missing $)
PathUtils.isValid('$.invalid['); // false (syntax error)isPointer()
Check if string is valid JSON Pointer.
PathUtils.isPointer('/store/books'); // true
PathUtils.isPointer(''); // true (root)
PathUtils.isPointer('store/books'); // false (missing /)
PathUtils.isPointer('$.store'); // false (JSONPath, not pointer)Path Comparison
equals()
Compare two paths for equality.
PathUtils.equals('$.store.books', '$["store"]["books"]'); // true
PathUtils.equals('$.items[0]', '$.items[1]'); // falsestartsWith()
Check if path starts with prefix.
const path = '$.store.books[0].title';
PathUtils.startsWith(path, '$.store'); // true
PathUtils.startsWith(path, '$.store.books'); // true
PathUtils.startsWith(path, '$.users'); // falsecontains()
Check if path contains segment.
const path = '$.store.books[0].title';
PathUtils.contains(path, 'books'); // true
PathUtils.contains(path, 0); // true
PathUtils.contains(path, 'users'); // falsePath Manipulation
replace()
Replace segment in path.
const path = '$.store.books[0].title';
const replaced = PathUtils.replace(path, 'books', 'magazines');
console.log(replaced); // '$.store.magazines[0].title'
// Replace index
const replaced2 = PathUtils.replace(path, 0, 5);
console.log(replaced2); // '$.store.books[5].title'remove()
Remove segment from path.
const path = '$.store.books[0].title';
const removed = PathUtils.remove(path, 'title');
console.log(removed); // '$.store.books[0]'Escaping and Unescaping
escape()
Escape special characters in property names.
PathUtils.escape('user name'); // 'user name' (needs quotes)
PathUtils.escape('items[0]'); // 'items[0]' (needs quotes)
PathUtils.escape('simple'); // 'simple' (no quotes needed)unescape()
Unescape property names.
PathUtils.unescape('"user name"'); // 'user name'
PathUtils.unescape("'items[0]'"); // 'items[0]'Pointer Utilities
splitPointer()
Split JSON Pointer into segments.
const pointer = '/store/books/0/title';
const segments = PathUtils.splitPointer(pointer);
console.log(segments); // ['store', 'books', '0', 'title']joinPointer()
Join segments into JSON Pointer.
const segments = ['store', 'books', '0', 'title'];
const pointer = PathUtils.joinPointer(segments);
console.log(pointer); // '/store/books/0/title'escapePointer()
Escape special characters in JSON Pointer.
// Escape ~ and /
PathUtils.escapePointer('path/with/slashes'); // 'path~1with~1slashes'
PathUtils.escapePointer('tilde~char'); // 'tilde~0char'unescapePointer()
Unescape JSON Pointer.
PathUtils.unescapePointer('path~1with~1slashes'); // 'path/with/slashes'
PathUtils.unescapePointer('tilde~0char'); // 'tilde~char'Practical Examples
Build Dynamic Paths
// Build path from user input
function buildUserPath(category: string, index: number, field: string) {
return PathUtils.build(['categories', category, 'items', index, field]);
}
const path = buildUserPath('electronics', 0, 'price');
console.log(path); // '$.categories.electronics.items[0].price'Convert Between Formats
// Accept both JSONPath and JSON Pointer
function queryByPath(path: string, data: any) {
let jsonPath: string;
if (PathUtils.isPointer(path)) {
jsonPath = PathUtils.fromPointer(path);
} else {
jsonPath = path;
}
return JSONPath.query(jsonPath, data);
}
// Works with both formats
await queryByPath('$.items[0]', data);
await queryByPath('/items/0', data);Path Navigation
// Navigate to parent and siblings
const currentPath = '$.store.books[2].title';
// Get parent
const bookPath = PathUtils.parent(currentPath);
// '$.store.books[2]'
// Get sibling properties
const authorPath = PathUtils.replace(currentPath, 'title', 'author');
// '$.store.books[2].author'
const pricePath = PathUtils.replace(currentPath, 'title', 'price');
// '$.store.books[2].price'Validate User Input
function safeQuery(userPath: string, data: any) {
// Validate path
if (!PathUtils.isValid(userPath)) {
throw new Error('Invalid JSONPath expression');
}
// Normalize for consistency
const normalized = PathUtils.normalize(userPath);
// Execute query
return JSONPath.query(normalized, data);
}Generate Breadcrumbs
function generateBreadcrumbs(path: string) {
const components = PathUtils.parse(path);
const breadcrumbs = [];
let currentPath = '$';
for (const component of components.slice(1)) {
if (component.type === 'property') {
currentPath = PathUtils.append(currentPath, `.${component.value}`);
breadcrumbs.push({
label: component.value,
path: currentPath
});
}
}
return breadcrumbs;
}
const breadcrumbs = generateBreadcrumbs('$.store.books[0].title');
// [
// { label: 'store', path: '$.store' },
// { label: 'books', path: '$.store.books' },
// { label: 'title', path: '$.store.books[0].title' }
// ]TypeScript Support
// Type-safe path components
interface PathComponent {
type: 'root' | 'property' | 'index' | 'wildcard' | 'slice' | 'filter' | 'recursive';
value: string | number;
}
// Type-safe utilities
const components: PathComponent[] = PathUtils.parse(path);
const path: string = PathUtils.stringify(components);
const pointer: string = PathUtils.toPointer(path);Performance Notes
Path utilities are lightweight and fast:
// Fast operations (< 1ms)
PathUtils.parse(path);
PathUtils.normalize(path);
PathUtils.toPointer(path);
// Very fast (< 0.1ms)
PathUtils.isValid(path);
PathUtils.equals(path1, path2);No significant performance concerns for typical usage.
See Also
- JSONPath Syntax - Path syntax reference
- Result Types - Working with results
- API Reference - Complete utility API
- RFC 6901 - JSON Pointer specification