0.5.0 • Published 2 years ago

@fosfad/json-pointer v0.5.0

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

JSON Pointer

This package contains TypeScript implementation for JavaScript Object Notation (JSON) Pointer (RFC 6901), also known as JSON Pointer.

If you are looking for Relative JSON Pointer implementation, check out @fosfad/relative-json-pointer package.

At this moment the package is not stable. We are thinking and experimenting with its design and API. Breaking changes are possible. Do not use it in production!

What is JSON Pointer

JSON Pointer defines a string syntax for identifying a specific value within a JSON document.

Take a look at following JSON document:

{
  "song": {
    "author": "State Azure",
    "title": "Fragments",
    "tags": ["ambient", "drone"]
  }
}

If we need to point to "Fragments" value, JSON Pointer will look like /song/title. If we want to point to "drone" value, then JSON Pointer will look like /song/tags/1.

JSON String Representation and URI Fragment Identifier Representation

JSON Pointer may have 2 representations: JSON String Representation and URI Fragment Identifier Representation:

  • JSON String Representation means JSON Pointer string should be formatted as a value suitable for being placed into JSON strings: {"someFieldThatContainsPointer": "/song/tags/1"}. All instances of quotation mark ", reverse solidus \, and control (%x00-1F) characters must be escaped.
  • URI Fragment Identifier Representation means JSON Pointer string should be formatted as a value suitable for being placed into URI fragment: https://example.com/song.json#/song/tags/1. It starts with # and percent-encoding is applied to some characters that are not allowed within URI fragments.

Usage

Installation

This package is available in npm Registry:

npm install @fosfad/json-pointer

API

Managing JSON Pointer

The package exposes JsonPointer type. It's simple object with only 1 field:

  • referenceTokens (array of strings) - reference tokens separated by a / character, also known as path segments. Empty array means JSON Pointer points to the whole document

There is no need to build this object manually, there are some helper functions described below.

parseJsonPointerFromString function

Parses input string into JsonPointer object.

Passing invalid string to the method will result into InvalidPointerSyntax error.

Usage examples:

import { parseJsonPointerFromString } from '@fosfad/json-pointer';

const jsonPointer = parseJsonPointerFromString('/foo/bar/hello world');

console.log(jsonPointer.referenceTokens); // Output: [ 'foo', 'bar', 'hello world' ]
createStringFromJsonPointer function

Creates a string from JsonPointer object.

Usage examples:

import { createStringFromJsonPointer } from '@fosfad/json-pointer';

const jsonPointerString = createStringFromJsonPointer({
  referenceTokens: ['foo', 'bar', 'hello world'],
});

console.log(jsonPointerString); // Output: /foo/bar/hello world
isValidJsonPointer function

Validates input string to be valid JSON Pointer.

Usage examples:

import { isValidJsonPointer } from '@fosfad/json-pointer';

console.log(isValidJsonPointer('')); // Output: true
console.log(isValidJsonPointer('/')); // Output: true
console.log(isValidJsonPointer('foo')); // Output: false
console.log(isValidJsonPointer('#foo')); // Output: false

// The package does not support URI Fragment Identifier Representation,
// see FAQ below
console.log(isValidJsonPointer('#')); // Output: false
console.log(isValidJsonPointer('#/')); // Output: false
escapeReferenceToken function

Escapes reference token according to the specification.

Transformations made by the function in following order:

  1. ~~0
  2. /~1

Usage examples:

import { escapeReferenceToken } from '@fosfad/json-pointer';

console.log(escapeReferenceToken('hello world')); // Output: hello world
console.log(escapeReferenceToken('hello~world')); // Output: hello~0world
console.log(escapeReferenceToken('hello/world')); // Output: hello~1world
unescapeReferenceToken function

Unescapes reference token according to the specification.

Transformations made by the function in following order:

  1. ~1/
  2. ~0~

Usage examples:

import { unescapeReferenceToken } from '@fosfad/json-pointer';

console.log(unescapeReferenceToken('hello%20world')); // Output: hello%20world
console.log(unescapeReferenceToken('hello~0world')); // Output: hello~world
console.log(unescapeReferenceToken('hello~1world')); // Output: hello/world
isJsonPointer function

Type guard for JsonPointer type.

Usage examples:

import { isJsonPointer } from '@fosfad/json-pointer';

console.log(
  isJsonPointer({
    referenceTokens: [],
  }),
); // Output: true

console.log(
  isJsonPointer({
    referenceTokens: ['foo', '123', ''],
  }),
); // Output: true

console.log(
  isJsonPointer({
    referenceTokens: ['foo', 123, true, null, undefined], // reference token may be only strings
  }),
); // Output: false
createJsonPointerFromReferenceTokens function

Helper factory for creating JSON Pointer from array of strings (reference tokens).

Usage examples:

import { createJsonPointerFromReferenceTokens } from '@fosfad/json-pointer';

console.log(createJsonPointerFromReferenceTokens(['a', 'b', 'c']));

Processing JSON documents

Functions for processing JSON Pointers are designed to work only with JSON-like JavaScript structures, like those returned by JSON.parse() method. If these functions meet undefined, Function or Symbol types or Infinity and NaN numbers, then behavior is not clear because these types and values are not explicitly supported by the library. It may be changed in the future, so you may create an issue describing your use case why you and others may need it.

getValueAtJsonPointer function

Gets value from JSON by JSON Pointer. This method accepts JSON, JSON Pointer (it may be a string or JsonPointer object) and returns JSON value resolved by given Pointer.

If JSON Pointer references a nonexistent value, PointerReferencesNonexistentValue error will be thrown.

Usage examples:

import {
  JsonPointer,
  parseJsonPointerFromString,
  getValueAtJsonPointer,
  PointerReferencesNonexistentValue,
} from '@fosfad/json-pointer';

const json = {
  song: {
    author: 'State Azure',
    title: 'Fragments',
    tags: ['ambient', 'drone'],
  },
};

console.log(getValueAtJsonPointer(json, parseJsonPointerFromString('/song/tags/1'))); // Output: drone

console.log(getValueAtJsonPointer(json, '')); // Output: { song: { author: 'State Azure', title: 'Chill Impromtu', tags: [ 'ambient', 'drone' ] } }
console.log(getValueAtJsonPointer(json, '/song')); // Output: { author: 'State Azure', title: 'Chill Impromtu', tags: [ 'ambient', 'drone' ] }
console.log(getValueAtJsonPointer(json, '/song')); // Output: State Azure
console.log(getValueAtJsonPointer(json, '/song/tags')); // Output: [ 'ambient', 'drone' ]
console.log(getValueAtJsonPointer(json, '/song/tags/1')); // Output: drone

try {
  getValueAtJsonPointer(json, '/foo/bar');
} catch (error: unknown) {
  if (error instanceof PointerReferencesNonexistentValue) {
    const jsonPointerString = createStringFromJsonPointer(error.jsonPointer);
    const nonexistentValueJsonPointerString = createStringFromJsonPointer(error.nonexistentValueJsonPointer);

    console.log(`Pointer ${jsonPointerString} references nonexistent value: ${nonexistentValueJsonPointerString}`);
  }
}
valueExistsAtJsonPointer function

Checks value exists in JSON at given JSON Pointer. This method accepts JSON, JSON Pointer (it may be a string or JsonPointer object) and returns boolean that indicates does value exist or not.

Usage examples:

import {
  JsonPointer,
  createStringFromJsonPointer,
  getValueAtJsonPointer,
  PointerReferencesNonexistentValue,
} from '@fosfad/json-pointer';

const json = {
  song: {
    author: 'State Azure',
    title: 'Fragments',
    tags: ['ambient', 'drone'],
  },
};

console.log(
  valueExistsAtJsonPointer(
    json,
    createStringFromJsonPointer({
      referenceTokens: ['song', 'tags', '1'],
    }),
  ),
); // Output: true

console.log(valueExistsAtJsonPointer(json, '')); // Output: true
console.log(valueExistsAtJsonPointer(json, '/song')); // Output: true
console.log(valueExistsAtJsonPointer(json, '/song')); // Output: true
console.log(valueExistsAtJsonPointer(json, '/song/tags')); // Output: true
console.log(valueExistsAtJsonPointer(json, '/song/tags/1')); // Output: true

console.log(valueExistsAtJsonPointer(json, '/foo/bar')); // Output: false

FAQ

Is URI Fragment Identifier Representation supported?

No. You should remove # from the beginning of the string and then decode string with decodeURI() function.

0.5.0

2 years ago

0.4.0

2 years ago

0.3.0

2 years ago

0.2.0

2 years ago

0.1.0

2 years ago

0.0.3

2 years ago

0.0.2

2 years ago

0.0.1

2 years ago