JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 2286
  • Score
    100M100P100Q117747F
  • License MIT

JSONPath, JSON Pointer and JSON Patch

Package Exports

  • json-p3
  • json-p3/dist/json-p3.cjs.js
  • json-p3/dist/json-p3.esm.js
  • json-p3/dist/json-p3.iife.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (json-p3) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

JSON P3

JSONPath, JSON Patch and JSON Pointer for JavaScript.

LICENSE Tests NPM npm type definitions


Table of Contents

Install

Node.js

Use npm:

npm install --save json-p3

Or yarn:

yarn add json-p3

Or pnpm:

pnpm add json-p3

And use ES module imports:

import { query } from "json-p3";

const data = {
  players: [{ name: "Sue" }, { name: "John" }, { name: "Sally" }],
  visitors: [{ name: "Brian" }, { name: "Roy" }],
};

const nodes = query("$..name", data);
console.log(nodes.values());
// [ 'Sue', 'John', 'Sally', 'Brian', 'Roy' ]

Or CommonJS modules:

const { query } = require("json-p3");

const data = {
  players: [{ name: "Sue" }, { name: "John" }, { name: "Sally" }],
  visitors: [{ name: "Brian" }, { name: "Roy" }],
};

const nodes = query("$..name", data);
console.log(nodes.values());
// [ 'Sue', 'John', 'Sally', 'Brian', 'Roy' ]

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");
  console.log(nodes.values());
  // [ 'Sue', 'John', 'Sally', 'Brian', 'Roy' ]
</script>

Or use a CDN:

<script src="https://cdn.jsdelivr.net/npm/json-p3@0.1.0/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");
  console.log(nodes.values());
  // [ 'Sue', 'John', 'Sally', 'Brian', 'Roy' ]
</script>

JSONPath

Retrieve values from JSON-like data using JSONPath query expressions. We strictly follow standards described in the IETF JSONPath draft.

import { jsonpath } from "json-p3";

const data = {
  users: [
    { name: "Sue", score: 100 },
    { name: "John", score: 86 },
    { name: "Sally", score: 84 },
    { name: "Jane", score: 55 },
  ],
};

const nodes = jsonpath.query("$.users[?@.score < 100].name", data);
console.log(nodes.values()); // [ 'John', 'Sally', 'Jane' ]

The result of jsonpath.query() is an instance of JSONPathNodeList. That is a list of JSONPathNode objects, one node for each value in the target JSON document matching the query. Each node has a:

  • value - The value found in the target JSON document. This could be an array, object or primitive value.
  • location - An array of property names and array indices that were required to reach the node's value in the target JSON document.
  • path - The normalized JSONPath to this node in the target JSON document.

Use JSONPathNodeList.paths() to retrieve all node paths.

// .. continued from above
console.log(nodes.paths());

Output:

[
  "$['users']['1']['name']",
  "$['users']['2']['name']",
  "$['users']['3']['name']"
]

And JSONPathNodeList.locations() to get an array of node locations.

// .. continued from above
console.log(nodes.locations());

Output:

[
  [ 'users', 1, 'name' ],
  [ 'users', 2, 'name' ],
  [ 'users', 3, 'name' ]
]

JSONPathNodeList objects are iterable too.

// .. continued from above
for (const node of nodes) {
  console.log(`${node.value} @ ${node.path}`);
}

Output:

John @ $['users'][1]['name']
Sally @ $['users'][2]['name']
Jane @ $['users'][3]['name']

You can also compile a JSONPath query for repeated use against different data.

import { jsonpath } from "json-p3";

const data = {
  users: [
    { name: "Sue", score: 100 },
    { name: "John", score: 86 },
    { name: "Sally", score: 84 },
    { name: "Jane", score: 55 },
  ],
};

const path = jsonpath.compile("$.users[?@.score < 100].name");
const nodes = path.query(data);
console.log(nodes.values()); // [ 'John', 'Sally', 'Jane' ]

JSON Pointer

Identify a single value in JSON-like data, as per RFC 6901. Use jsonpointer.resolve() to retrieve the value.

import { jsonpointer } from "json-p3";

const data = {
  users: [
    { name: "Sue", score: 100 },
    { name: "John", score: 86 },
    { name: "Sally", score: 84 },
    { name: "Jane", score: 55 },
  ],
};

const rv = jsonpointer.resolve("/users/1", data);
console.log(rv); // { name: 'John', score: 86 }

If the pointer can't be resolved against the argument JSON value, one of JSONPointerIndexError, JSONPointerKeyError or JSONPointerTypeError is thrown. All three exceptions inherit from JSONPointerResolutionError.

// .. continued from above
const rv = jsonpointer.resolve("/users/1/age", data);
// JSONPointerKeyError: no such property ("/users/1/age")

A fallback value can be given as a third argument, which will be returned in the event of a JSONPointerResolutionError.

// .. continued from above
const rv = jsonpointer.resolve("/users/1/age", data, -1);
console.log(rv); // -1

You can also create an instance of JSONPointer then resolve it against different data.

import { JSONPointer } from "json-p3";

const someData = {
  users: [
    { name: "Sue", score: 100 },
    { name: "John", score: 86 },
    { name: "Sally", score: 84 },
  ],
};

const otherData = {
  users: [{ name: "Brian" }, { name: "Roy" }],
};

const pointer = new JSONPointer("/users/1");
console.log(pointer.resolve(someData)); // { name: 'John', score: 86 }
console.log(pointer.resolve(otherData)); // { name: 'Roy' }

JSON Patch

Apply a JSON Patch (RFC 6902) to some data. A JSON Patch defines update operation to perform on a JSON document. Data is modified in place..

import { jsonpatch } from "json-p3";

const ops = [
  { op: "add", path: "/some/foo", value: { foo: {} } },
  { op: "add", path: "/some/foo", value: { bar: [] } },
  { op: "copy", from: "/some/other", path: "/some/foo/else" },
  { op: "add", path: "/some/foo/bar/-", value: 1 },
];

const data = { some: { other: "thing" } };
jsonpatch.apply(ops, data);
console.log(data);
// { some: { other: 'thing', foo: { bar: [Array], else: 'thing' } } }

Use the JSONPatch class to create a patch for repeated application.

import { JSONPatch } from "json-p3";

const patch = new JSONPatch([
  { op: "add", path: "/some/foo", value: { foo: {} } },
  { op: "add", path: "/some/foo", value: { bar: [] } },
  { op: "copy", from: "/some/other", path: "/some/foo/else" },
  { op: "add", path: "/some/foo/bar/-", value: 1 },
]);

const data = { some: { other: "thing" } };
patch.apply(data);
console.log(data);
// { some: { other: 'thing', foo: { bar: [Array], else: 'thing' } } }

JSONPatch also offers a builder API for constructing JSON patch documents. We use strings as JSON Pointers in this example, but existing JSONPointer objects are OK too.

import { JSONPatch } from "json-p3";

const data = { some: { other: "thing" } };

const patch = new JSONPatch()
  .add("/some/foo", { foo: [] })
  .add("/some/foo", { bar: [] })
  .copy("/some/other", "/some/foo/else")
  .add("/some/foo/bar/-", "/some/foo/else");

patch.apply(data);
console.log(JSON.stringify(data, undefined, "  "));

Output:

{
  "some": {
    "other": "thing",
    "foo": {
      "bar": ["/some/foo/else"],
      "else": "thing"
    }
  }
}