JSON P3
JSONPath, JSON Pointer and JSON Patch for JavaScript.
JSONPath (RFC 9535) is a mini language for selecting values from JSON-like data. A JSONPath query has the potential to return multiple values from a data structure, along with their locations. This implementation is non-evaluating and read-only.
JSON Pointer (RFC 6901) is a syntax for targeting a single value in JSON-like data. JSON Pointers can be resolved against data to retrieve the value, or used as part of a JSON Patch operation.
JSON Patch (RFC 6902) is a standard for describing update operations to perform on JSON-like data. You can apply a patch to add, remove, replace, copy and move values within a JSON document.
We use the term JSON-like data to describe arbitrary, possibly nested, JavaScript arrays and objects, plus primitive strings, numbers, booleans and null, as you might expect from JSON.parse(). When traversing JSON-like data, we only resolve an object's direct properties, and the length property of arrays and strings is ignored.
Install
Node.js
Install JSON P3 using your preferred project manager:
- npm
- yarn
- pnpm
npm install --save json-p3
yarn add json-p3
pnpm add json-p3
And import the module:
- ESM
- CJS
import { query } from "json-p3";
const { query } = require("json-p3");
Browser
Download and include JSON P3 in a script tag:
<script src="path/to/json-p3.iife.min.js"></script>
<script>
  const data = {
    players: [{ name: "Sue" }, { name: "John" }, { name: "Sally" }],
    visitors: [{ name: "Brian" }, { name: "Roy" }],
  };
  const nodes = json_p3.query("$..name", data);
  console.log(nodes.values());
  // [ 'Sue', 'John', 'Sally', 'Brian', 'Roy' ]
</script>
Or use a CDN
<script src="https://cdn.jsdelivr.net/npm/json-p3@1.1.1/dist/json-p3.iife.min.js"></script>
<script>
  const data = {
    players: [{ name: "Sue" }, { name: "John" }, { name: "Sally" }],
    visitors: [{ name: "Brian" }, { name: "Roy" }],
  };
  const nodes = json_p3.query("$..name", data);
  console.log(nodes.values());
  // [ 'Sue', 'John', 'Sally', 'Brian', 'Roy' ]
</script>
Example
This example uses a JSONPath query to find players with a low score, converts each node from the query result to a JSONPointer, then uses that pointer to build a JSONPatch that, when applied to our original data, boosts each player's score by 20.
import { query, JSONPatch } from "json-p3";
const data = {
  teams: [
    {
      name: "A Team",
      players: [
        {
          name: "Sue",
          score: 110,
        },
        {
          name: "John",
          score: 86,
        },
      ],
    },
    {
      name: "B Team",
      players: [
        {
          name: "Sally",
          score: 84,
        },
        {
          name: "Jane",
          score: 55,
        },
      ],
    },
  ],
};
const nodes = query("$..players[?@.score < 90]", data);
const patch = new JSONPatch();
for (const node of nodes) {
  const pointer = node.toPointer().join("score");
  patch.replace(pointer, node.value.score + 20);
}
patch.apply(data);
console.log(JSON.stringify(data, undefined, "  "));
{
  "teams": [
    {
      "name": "A Team",
      "players": [
        {
          "name": "Sue",
          "score": 110
        },
        {
          "name": "John",
          "score": 106
        }
      ]
    },
    {
      "name": "B Team",
      "players": [
        {
          "name": "Sally",
          "score": 104
        },
        {
          "name": "Jane",
          "score": 75
        }
      ]
    }
  ]
}