npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

jsonpathly

v3.0.1

Published

RFC 9535 compliant JSONPath query library for TypeScript/JavaScript - secure, fast, and dependency-free

Readme

jsonpathly

npm version codecov Node.js License: MIT

A secure, expression-evaluation-free JSONPath implementation for TypeScript/JavaScript with RFC 9535 compliance.

Live Demo | RFC 9535 Specification

Features

  • RFC 9535 compliant - Follows the official JSONPath specification
  • Secure - No dynamic code execution, no injection vulnerabilities
  • TypeScript native - Full type definitions included
  • Dual module - Works with ESM and CommonJS
  • Browser ready - Works in Node.js and browsers

Install

npm install jsonpathly

Quick Start

import { query, paths } from "jsonpathly";

const championship = {
  name: "World Chess Championship 2023",
  players: [
    { name: "Ding Liren", rating: 2788, country: "China" },
    { name: "Ian Nepomniachtchi", rating: 2795, country: "Russia" },
  ],
};

// Query values
query(championship, "$.players[*].name");
// => ["Ding Liren", "Ian Nepomniachtchi"]

// Get paths
paths(championship, "$.players[0]");
// => ["$['players'][0]"]

// Filter expressions
query(championship, "$.players[[email protected] > 2790].name");
// => ["Ian Nepomniachtchi"]

JSONPath Syntax

JSONPath expressions start with $ (root) and can use dot or bracket notation:

$.players[0].name
$['players'][0]['name']

Operators

| Operator | Description | | :------------------------ | :-------------------------------------------------------------- | | $ | Root element | | @ | Current element in filter expressions | | * | Wildcard - matches all elements | | .. | Recursive descent | | .<name> | Dot-notated child | | ['<name>'] | Bracket-notated child | | [<index>] | Array index | | [start:end:step] | Array slice | | [?<expression>] | Filter expression | | [<expr>, <expr>] | Union - multiple selectors |

Filter Operators

| Operator | Description | Example | | :--------- | :------------------------------------------------------- | :--------------------------------------------- | | == | Equal | $[[email protected] == 'Grandmaster'] | | != | Not equal | $[[email protected] != 'Russia'] | | < | Less than | $[[email protected] < 2700] | | <= | Less than or equal | $[[email protected] <= 2700] | | > | Greater than | $[[email protected] > 2800] | | >= | Greater than or equal | $[[email protected] >= 2800] | | && | Logical AND | $[[email protected] > 2700 && @.active] | | \|\| | Logical OR | $[[email protected] \|\| @.challenger] | | ! | Logical NOT | $[[email protected]] | | =~ | Regex match | $[[email protected] =~ /^Magnus/i] |

RFC 9535 Functions

| Function | Description | Example | | :----------- | :----------------------------------- | :--------------------------------------------- | | length() | Length of string, array, or object | $[?length(@.name) > 10] | | count() | Count of elements in a nodelist | $[?count(@.titles[*]) > 5] | | match() | Full string regex match | $[?match(@.title, '^GM.*')] | | search() | Regex search within string | $[?search(@.name, 'Kasparov')] | | value() | Extract value from nodelist | $[?value(@.achievements[0]) == 'World Champion'] |

Extension Operators

| Operator | Description | Example | | :--------- | :------------------------------------------- | :-------------------------------------------------- | | in | Value exists in array | $[[email protected] in ['FIDE', 'USCF']] | | nin | Value not in array | $[[email protected] nin ['loss']] | | subsetof | Left is subset of right | $[[email protected] subsetof ['GM', 'IM', 'FM']] | | anyof | Any element in common | $[[email protected] anyof ['positional', 'tactical']] | | noneof | No elements in common | $[[email protected] noneof ['time trouble']] | | size | Array/string length equals | $[[email protected] size 5] | | empty | Array/string is empty | $[[email protected] empty] |

API

query(data, path, options?)

Query JSON data and return matching values.

import { query } from "jsonpathly";

const legends = {
  champions: [
    { name: "Garry Kasparov", era: "1985-2000", rating: 2851 },
    { name: "Magnus Carlsen", era: "2013-2023", rating: 2882 },
  ],
};

query(legends, "$.champions[*].name");
// => ["Garry Kasparov", "Magnus Carlsen"]

query(legends, "$.champions[0].era");
// => "1985-2000"

Options:

| Option | Type | Description | | :--------------- | :-------- | :--------------------------------------------------------------- | | hideExceptions | boolean | Return undefined instead of throwing (or [] if returnArray is true) | | returnArray | boolean | Always return results as an array |

paths(data, path, options?)

Get normalized paths to matching elements.

import { paths } from "jsonpathly";

const tournament = {
  candidates: [
    { player: "Bobby Fischer", year: 1971 },
    { player: "Anatoly Karpov", year: 1974 },
  ],
};

paths(tournament, "$..player");
// => ["$['candidates'][0]['player']", "$['candidates'][1]['player']"]

Options:

| Option | Type | Description | | :--------------- | :-------- | :--------------------------------------- | | hideExceptions | boolean | Return empty array instead of throwing |

parse(path)

Parse a JSONPath expression into an AST.

import { parse } from "jsonpathly";

parse("$.players[0].rating");
// => { type: 'root', next: { type: 'subscript', ... } }

stringify(ast)

Convert an AST back to a JSONPath string.

import { parse, stringify } from "jsonpathly";

stringify(parse("$.champions[*].name"));
// => "$.champions[*].name"

JSONPathSyntaxError

Custom error class for syntax errors.

import { query, JSONPathSyntaxError } from "jsonpathly";

try {
  query({}, "$[invalid");
} catch (e) {
  if (e instanceof JSONPathSyntaxError) {
    console.log("Invalid JSONPath:", e.message);
  }
}

Security

jsonpathly is designed with security in mind:

  • No dynamic code execution - Expressions are parsed into an AST and evaluated safely
  • No code injection - Script expressions $(...) are not supported
  • I-Regexp compliance - Regex patterns in match() and search() are validated against RFC 9485

Comparison with Other Libraries

For a comparison with other JSONPath implementations, see json-path-comparison.

Key differences:

  • Uses a Peggy parser instead of dynamic execution
  • Follows RFC 9535 semantics for edge cases
  • Normalized paths use single quotes per RFC 9535

Breaking Changes in v3.0.0

  • Path format changed: paths() now returns RFC 9535 normalized format with single quotes:
    Before: $["players"][0]["name"]
    After:  $['players'][0]['name']
  • Node.js 18+ required

Requirements

  • Node.js >= 18

License

MIT