jsonpos

Get the textual position of a property in a JSON text

Usage no npm install needed!

<script type="module">
  import jsonpos from 'https://cdn.skypack.dev/jsonpos';
</script>

README

npm version downloads build status coverage status Language grade: JavaScript

jsonpos

Get the text position [start, end] of a property in a JSON document.

Given the following JSON:

{
    "foo": {
        "bar": "baz"
               ^^^^^
    }
}

The position of /foo/bar (or ["foo", "bar"] if provided as an array), is:

{
    start: { line: 3, column: 16, offset: 30 },
    end: { line: 3, column: 21, offset: 35 }
}

where offset is the character offset in the JSON string.

If the property "bar" is wanted, instead of the value, set markIdentifier to true, see Simple usage.

Install

npm i jsonpos or yarn add jsonpos

Versions

  • Since v2 this is a pure ESM package, and requires Node.js >=12.20
  • Since v3 the API has changed. The dataPath option has been renamed with changed semantics.
    • Dot-based (string) dataPath is now dotPath. It's not recommended to use as it's not safe for certain characters.
      • Also, it now requires an initial .. Only the path . represents the root object.
    • Array-based dataPath is now simply path.
      • An empty object represents the root object, like in v2.
    • New slash-based (string) pointerPath is allowed, following JSON Pointer encoding.

Simple usage

Definition

jsonpos( json, options: LocationOptions ): Location

where LocationOptions is:

interface LocationOptions
    markIdentifier?: boolean;

    // Only one of the following
    dotPath: string;
    path: Array< string | number >;
    pointerPath: string;
}

and Location is:

interface Location
{
    start: Position | undefined;
    end: Position | undefined;
}

where Position is:

interface Position
{
    line: number;
    column: number;
    offset: number;
}

As dot-separated textual path:

import { jsonpos } from 'jsonpos'

const loc = jsonpos(
    '{ "foo": { "bar": "baz" } }',
    { dotPath: '.foo.bar' }
);

Note that dot-separated paths are strongly advised against.

As /-separated textual path:

import { jsonpos } from 'jsonpos'

const loc = jsonpos(
    '{ "foo": { "bar": "baz" } }',
    { pointerPath: '/foo/bar' }
);

As array path:

import { jsonpos } from 'jsonpos'

const loc = jsonpos(
    '{ "foo": { "bar": "baz" } }',
    { path: [ 'foo', 'bar' ] }
);

Advanced usage

The jsonpos function is a shorthand for getLocation( getAstByString( json ), options )

Extract the AST (using json-to-ast) with getAstByString or getAstByObject. The result is an object of type ParsedJson:

interface ParsedJson
{
    json: any;
    jsonString: string;
    jsonAST: ValueNode; // ValueNode is a json-to-ast type
}

getAstByString

import { getAstByString } from 'jsonpos'

const ast = getAstByString( '{ "foo": "bar" }' );
const { json, jsonString, jsonAST } = ast;

getAstByObject

getAstByObject will stringify the JSON using JSON.stringify(obj, null, 4) and use that to parse the AST.

import { getAstByObject } from 'jsonpos'

const ast = getAstByObject( { foo: "bar" } );
const { json, jsonString, jsonAST } = ast;

getAstByObject takes an optional second argument indent which can be set to something else than 4 if necessary, e.g. 2:

const ast = getAstByObject( { foo: "bar" }, 2 );

getLocation

The getLocation takes an ast object as returned by getAstByString or getAstByObject and returns a Location object.

Definitins

getLocation( ast: ParsedJson, options: LocationOptions ): Location

Example

import { getAstByString, getLocation } from 'jsonpos'

const ast = getAstByString( '{ "foo": "bar" }' );
const loc = getLocation( ast, { pointerPath: '/foo' } );