From f97d10dc6b87922323ddf2d8cdfcbbb5b6999389 Mon Sep 17 00:00:00 2001 From: James Prior Date: Fri, 22 Sep 2023 11:09:12 +0100 Subject: [PATCH] docs: intro to function extensions --- docs/docs/guides/jsonpath-functions.md | 37 ++++++++++++++++++++++++-- docs/docs/guides/jsonpath-syntax.md | 2 +- docs/docs/intro.mdx | 6 ++--- docs/docs/quick-start.md | 10 +++---- package-lock.json | 4 +-- src/index.ts | 1 + 6 files changed, 47 insertions(+), 13 deletions(-) diff --git a/docs/docs/guides/jsonpath-functions.md b/docs/docs/guides/jsonpath-functions.md index 23ea485..3751e56 100644 --- a/docs/docs/guides/jsonpath-functions.md +++ b/docs/docs/guides/jsonpath-functions.md @@ -2,7 +2,7 @@ ## Standard functions -These are the standard, built-in function available to JSONPath [filters](./jsonpath-syntax.md#filters). You can also create your own [function extensions](#function-extensions). +These are the standard, built-in functions available to JSONPath [filters](./jsonpath-syntax.md#filters). You can also create your own [function extensions](#function-extensions). ### `count()` @@ -72,4 +72,37 @@ Please see [Section 2.4.3](https://datatracker.ietf.org/doc/html/draft-ietf-json ## Function extensions -TODO: +Add, remove or replace [filter functions](./jsonpath-syntax.md#filter-functions) by updating the [function register](../api/classes/jsonpath.JSONPathEnvironment.md#functionregister) on a [`JSONPathEnvironment`](../api/classes/jsonpath.JSONPathEnvironment.md). It is a regular [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map), mapping function names to objects implementing the [`FilterFunction`](../api/interfaces/jsonpath.functions.FilterFunction.md) interface. + +:::info +You can update the function register on the _default environment_ (`import { DEFAULT_ENVIRONMENT } from "json-p3"`), and use convenience functions like [`query()`](../quick-start.md#jsonpath) and [`compile()`](../quick-start.md#compilation). Here we'll create a new `JSONPathEnvironment`, then use its methods directly. +::: + +Every filter function must define the types of its parameters and the type of its return value, according to the JSONPath specification's [type system](https://datatracker.ietf.org/doc/html/draft-ietf-jsonpath-base-20#name-type-system-for-function-ex). This example implements a `typeof()` function, which accepts a parameter of [`ValueType`](../api/enums/jsonpath.functions.FunctionExpressionType.md) and returns a `ValueType`. + +```typescript +import { + FilterFunction, + FunctionExpressionType, + JSONPathEnvironment, +} from "json-p3"; + +class TypeOfFilterFunction implements FilterFunction { + readonly argTypes = [FunctionExpressionType.ValueType]; + readonly returnType = FunctionExpressionType.ValueType; + + public call(value: unknown): string { + return typeof value; + } +} +``` + +We would then register an instance of `TypeOf` with a `JSONPathEnvironment`, and use the environment's `query()`, `compile()` or `match()` methods. + +```typescript +// .. continued from above +const env = new JSONPathEnvironment(); +env.functionRegister.set("typeof", new TypeOfFilterFunction()); + +const nodes = env.query("$.users[?typeof(@.score) == 'number']"); +``` diff --git a/docs/docs/guides/jsonpath-syntax.md b/docs/docs/guides/jsonpath-syntax.md index 542f5ca..22a7df5 100644 --- a/docs/docs/guides/jsonpath-syntax.md +++ b/docs/docs/guides/jsonpath-syntax.md @@ -1,6 +1,6 @@ # JSONPath Query Syntax -This page provides a casual introduction to JSONPath syntax described in the [IETF JSONPath draft](https://datatracker.ietf.org/doc/html/draft-ietf-jsonpath-base-20) specification. We follow it strictly, and test against the [JSONPath Compliance Test Suite](https://github.com/jsonpath-standard/jsonpath-compliance-test-suite). +This page provides a short introduction to JSONPath syntax described in the [IETF JSONPath draft](https://datatracker.ietf.org/doc/html/draft-ietf-jsonpath-base-20) specification. We follow it strictly, and test against the [JSONPath Compliance Test Suite](https://github.com/jsonpath-standard/jsonpath-compliance-test-suite). Imagine a JSON document as a tree structure, where each JSON object and array can contain more objects, arrays and scalar values. Every object, array and scalar value is a node in the tree, and the outermost value is the "root" node. diff --git a/docs/docs/intro.mdx b/docs/docs/intro.mdx index 3661939..776073c 100644 --- a/docs/docs/intro.mdx +++ b/docs/docs/intro.mdx @@ -7,13 +7,13 @@ import TabItem from "@theme/TabItem"; # JSON P3 -JSON P3 implements JSONPath following the [IETF JSONPath draft](https://datatracker.ietf.org/doc/html/draft-ietf-jsonpath-base-20) specification, JSON Pointer described by [RFC 6901](https://datatracker.ietf.org/doc/html/rfc6901), and JSON Patch described by [RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902). +JSONPath, JSON Pointer and JSON Patch for JavaScript. **[JSONPath](./quick-start.md#jsonpath)** 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. We strictly follow the [IETF JSONPath draft](https://datatracker.ietf.org/doc/html/draft-ietf-jsonpath-base-20). -**[JSON Pointer](./quick-start.md#json-pointer)** 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 Pointer](./quick-start.md#json-pointer)** ([RFC 6901](https://datatracker.ietf.org/doc/html/rfc6901)) 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](./quick-start.md#json-patch)** 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. +**[JSON Patch](./quick-start.md#json-patch)** ([RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902)) 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. diff --git a/docs/docs/quick-start.md b/docs/docs/quick-start.md index 6616587..20771de 100644 --- a/docs/docs/quick-start.md +++ b/docs/docs/quick-start.md @@ -199,8 +199,6 @@ console.log(pointer.to("2/baz/2").resolve(data)); // 6 Apply a JSON Patch ([RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902)) to some data with `jsonpatch.apply()`. **Data is modified in place.**. -### JSONPatch constructor - ```javascript import { jsonpatch } from "json-p3"; @@ -217,7 +215,11 @@ console.log(data); // { some: { other: 'thing', foo: { bar: [Array], else: 'thing' } } } ``` -`apply()` is a convenience function equivalent to `new JSONPatch(ops).apply(data)`. Use the [`JSONPatch`](./api/classes/jsonpatch.JSONPatch.md) constructor when you need to apply the same patch to multiple different data structures. +`apply()` is also re-exported from JSON P3's top-level namespace. + +### JSONPatch constructor + +`jsonpatch.apply()` is a convenience function equivalent to `new JSONPatch(ops).apply(data)`. Use the [`JSONPatch`](./api/classes/jsonpatch.JSONPatch.md) constructor when you need to apply the same patch to multiple different data structures. ```javascript import { JSONPatch } from "json-p3"; @@ -235,8 +237,6 @@ console.log(data); // { some: { other: 'thing', foo: { bar: [Array], else: 'thing' } } } ``` -`apply()` is also re-exported from JSON P3's top-level namespace. - ### Builder API `JSONPatch` objects offer a builder interface for constructing JSON patch documents. We use strings as JSON Pointers in this example, but existing `JSONPointer` objects are OK too. diff --git a/package-lock.json b/package-lock.json index 90bc75b..3a3a066 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "json-p3", - "version": "0.1.1", + "version": "0.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "json-p3", - "version": "0.1.1", + "version": "0.2.0", "license": "MIT", "devDependencies": { "@babel/cli": "^7.22.10", diff --git a/src/index.ts b/src/index.ts index 4c28040..910a826 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ export const version = "__VERSION__"; export * as jsonpath from "./path"; export { + DEFAULT_ENVIRONMENT, FunctionExpressionType, JSONPath, JSONPathEnvironment,