CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-jsonpath

Query JavaScript objects with JSONPath expressions using a robust and safe JSONPath engine for Node.js.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

path-processing.mddocs/

Path Processing

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.

Capabilities

Parse Function

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 components

Stringify Function

Convert 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"

Component Structure

Expression Types

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))

Operation and Scope

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 ..[...])

Advanced Usage Examples

Path Manipulation

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"

Path Analysis

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, ... }

Working with Query Results

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`);
});

Error Handling

Path processing functions handle various error conditions:

  • parse throws AssertionError if argument is not a string
  • parse throws Error for invalid JSONPath syntax
  • stringify throws AssertionError if no path provided
  • stringify throws Error if it can't find appropriate template for component
  • stringify throws Error if path format is not recognized

docs

index.md

manipulation.md

path-processing.md

querying.md

tile.json