Skip to main content

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.

info

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 install --save json-p3

And import the module:

import { query } from "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, " "));
output
{
"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
}
]
}
]
}