2.1.0 • Published 2 years ago

@twipped/jpath v2.1.0

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

@twipped/jpath

JPath is an object navigation and data aggregation library based upon the jsonpath specification, but not explicitly adhering to it. The most notable difference is that script blocks (statements inside parenthesis) are NOT executed within the scripting engine, but rather are evaluated as jpath substatements. Aside from this change, jpath should be fully backwards compatible with jsonpath.

Additionally, jpath provides a lot of functionality NOT present in the original jsonpath specification and implementation, such as a broad range of computational operators and collection manipulation, and a syntax for mapping over values.

Usage

npm install @twipped/jpath

In CommonJS:

const { compile } = require('@twipped/jpath');
const fn = compile('$.store.book.*');
const books = fn(data);

In ES6:

import { compile } from '@twipped/jpath';
const fn = compile('$.store.book.*');
const books = fn(data);

API

JPath.compile(path, options )

Parses the JPath string into an evaluatable function

  1. path - (string) The jpath to be parsed.
  2. options - Options object
  • operators: See below
  • cache: An JavaScript Map object to use for caching compiled functions for faster recall. Defaults to null

Returns: Function which takes a single data input and returns an array of results. Throws: SyntaxError. The exception will have line and column properties to indicate where the parsing error occurred.

JPath.compileSafe(path, options )

Same as above, except returns the results in the format of { fn, error } rather than throwing on parsing error.

JPath.execute(path, data, options )

Parses the JPath string and immediately executes it against the provided data.

  1. path - (string) The jpath to be parsed.
  2. data - A JS object or array to be read from
  3. options - Options object
  • operators: See below
  • cache: An JavaScript Map object to use for caching compiled functions for faster recall. Defaults to an internal singleton.

Returns: Function which takes a single data input and returns an array of results. Throws: SyntaxError. The exception will have line and column properties to indicate where the parsing error occurred.

JPath.parse(path, options )

Parses the JPath string into a manipulatable AST

  1. path - (string) The jpath to be parsed.
  2. options - Options object
  • operators: See below

Returns: Top level Statement object Throws: SyntaxError. The exception will have line and column properties to indicate where the parsing error occurred.

JPath.parseSafe(path, options )

Same as above, except returns the results in the format of { ast, error } rather than throwing on parsing error.

JPath Syntax

JPath uses a dot-notation and brackets syntax, same as JavaScript and JSONPath.

$.store.book[0].title
$['store']['book'][0]['title']

However, in JPath this is optional, and the same results can be accomplished with simple spaces. It is also possible to omit the leading $ from the path. However, it is not recommend that you use this in an entire path, as your property keys may be misinterpreted for operators.

store book 0 // `store book 2` fetches the third `book`
store mod 0  // `store mod 2` performs modulus 2 on the value of `store`

Whitespace is otherwise insignificant, so this is a perfectly valid path:

..book.* {
  %,
  title,
  price,
}

Property Identifiers

Following the same rules as JavaScript, property identifiers can only start with A-Z (caseinsensitive), $ and _ (underscore). They may also contain numbers.

Recursive Descent

The .. (double period) notation identifies that you are seeking any value identified immediately following the ...

Examples
@..bookRecursively scans every object in the current scope to find a value named book
@..[$.marker]Recursively scans every object from the current scope to find any values named with the value at $.marker
$..(1,2)Returns the second and third items from every array found in the data
$..?(isbn)Returns any objects which contain an isbn value.

Literals

JPath recognizes the true, false and null keywords as literal values, as well as any numbers, and text enclosed inside single or double quotes (ex: "hello"). Literal values can only exist at the beginning of an expression (which includes either side of an operator).

Unions

The comma (,) token allows you to return multiple discrete values from an expression.

Examples
$.a, $.bProduces a two item array containing the values of a and b
products.*.price (max *, min *)Produces a two item array of the smallest and largest prices
($.a, $.b) join ', 'Selects the values of a and b and joins them together into a single string result.

Slicing

Arrays and strings may be sliced using the bracket-colon notation: [start:end:step]

Examples
$.items[2:]Returns all items, skipping the first two.
$.items[-2:]Returns the last two items.
$.items[:2]Returns the first two items.
$.items[::2]Returns every other item.
$.items[::-1]Returns the array in items order.

Hashmaps

You can produce a keyed object by combining the Slice (:) and Union (,) operators.

index: %, title, price: price mul 0.5

Note that this does support the shortened notation where it is not needed to type title: title, however at least one property in the set must use a colon to mark the key, or else the set will be parsed as a union.

Mapping

An expression wrapped in curly braces ({ and }) is a Mapping expression. This will take the values received from the left of the Mapping, run the internal expression against each one, and output the non-null results.

$.products.* { productid, price mul 0.5 } Produces an array of arrays where each contains the productid and half the price.

Filtering

The filter statement takes all values from the left of the filter and iterates over them with the enclosed expression. If the expression returns any truthy result, then the value is outputted, otherwise it is excluded.

The scope of a filter expression is always the value being filtered, as is the initial value of the expression, except during a bracketed descent (eg, foo[?(something)]). In that case the initial value is the key of the value being filtered.

Scope Keywords

JPath statements are composed of multiple expressions. Any time the path is segmented by brackets, braces or parenthesis, that forms a new expression, and thus a new scope. Operators also cause multiple expressions, but they receive the parent scope.

Expressions may begin with one of four significant characters:

KeywordNameDescription
$RootTargets the top level of the data passed in to the expression.
@ScopeTargets the top level of the current expression.
#KeyWhen iterating over an object or array, contains the key of the current item.
%IndexWhen iterating over an object or array, contains the zero-based index of the current item.

If these are used in the middle of an expression (ex: $.foo.@.bar) then they will be treated as property keys (eg: foo["@"].bar).

Operators

JPath supports a full compliment of operators for manipulating data.

OperNameDescription
*All ValuesReturns all of the values in the collections to the left
~All Keys/IndexesReturns all keys of the collections to the left
===Strict EqualResults in a single true if the first value of both left and right expressions are strictly identical.
==Loose EqualResults in a single true if the first value of both left and right expressions are loosely identical.
!==Strict UnequalResults in a single true if the first value of both left and right expressions are not strictly identical.
!=Loose UnequalResults in a single true if the first value of both left and right expressions are not loosely identical.
<Less ThanResults in a single true if the first value of the left expression is smaller than the first value of the right expression.
<=Less Than or Equal ToResults in a single true if the first value of the left expression is smaller than or equal to the first value of the right expression.
>=Greater Than or Equal ToResults in a single true if the first value of the left expression is larger than or equal the first value of the right expression.
>Greater ThanResults in a single true if the first value of the left expression is larger than the first value of the right expression.
-MinusProduces the result of subtracting the first value of the right expression from the first value of the left expression
+PlusProduces the result of subtracting the first value of the right expression from the first value of the left expression
&&Logical AndReturns the right side results if the left side results contain truthy values, the left side results if not.
||Logical OrReturns the left side results if the left side results contain truthy values, the right side results if not.
??Null CoalesceReturns the left side results unless the results are empty, then returns the right side.
!FalseyResults in a single true if the statement to the right has a truthy value.
!!TruthyResults in a single true if the statement to the right is empty or contains no truthy values.
intCoerce to NumberAttempts to coerce all values produced by the statement right to numbers.
strCoerce to StringAttempts to coerce all values produced by the statement right to strings.
isMatching ResultsProduces a single true if expressions on both sides are strictly identical.
inIntersectionReturns all the values from the left side which exist in the results of the right side expression.
notDifferenceReturns all the values from the left side which are NOT in the results of the right side expression.
subsetExclusive IntersectionReturns all the values from the left side, but only if they all exist in the right side expression.
typeofType CompareProduces a single true if the first value of both expressions is the same data type (string, number, boolean, object, array).
ntypeofType MismatchProduces a single true if the first value of both expressions are not the same data type (string, number, boolean, object, array).
joinJoin ArrayJoins the values on the left side of the expression into a single string, using the first value on the right.
splitSplit ArraySplits every string value on the left using the first value of the right expression as the delimiter
keysCollection KeysOutputs the keys of any Object, Array, Set or Map received from the left expression.
valuesCollection ValuesOutputs the values of any Object, Array, Set or Map received from the left expression.
addAdditionAdds the first value on of the right expression to every value on the left.
subSubtractionSubtracts the first value on of the right expression from every value on the left.
mulMultiplicationMultiples every value of the left expression by the first value on the right.
divDivisionDivides every value of the left expression by the first value on the right.
modModulusReduces every value of the left expression to the modulo of the first value on the right.
expExponentReturns every value of the left expression, to the exponent of the first value on the right.
absAbsolute ValueOutputs the absolute value for every value in the left expression.
ceilValue CeilingRounds up every value from the left side expression to the nearest whole number
floorValue FloorRounds down every value from the left side expression to the nearest whole number
roundRound ValueRounds every value from the left side expression to the nearest whole number
minMinimum ValueOutputs the smallest numeric value from the result of the expression left of the operator
maxMaximum ValueOutputs the largest numeric value from the result of the expression left of the operator
sumSum of ValuesOutputs the sum of all numeric values in the result of the expression left of the operator
avgMean Average of ValuesOutputs the mean average of all numeric value in the result of the expression left of the operator
medMedian Average of ValuesOutputs the median average of all numeric value in the result of the expression left of the operator
stddevStandard DeviationOutputs the standard deviation of all numeric value in the result of the expression left of the operator
randomRandom of ValuesOutputs a single random value from the results of the expression left of the operator
firstFirst of ValeusOutputs the first value from the results of the expression left of the operator
lastLast of ValuesOutputs the left value from the results of the expression left of the operator
uniqueDe-duplicate ValuesRemoves duplicate values from the results of the expression left of the operator
sortSort ValuesSorts the results of the expression left of the operator, using a case-insensitive natural sort that ignores punctuation.
anyAny Value is TruthyProduces a single true if any of the results of the expression left of the operator are truthy.
allAll Values Are TruthyProduces a single true if all of the results of the expression left of the operator are truthy.
noneNo Value is TruthyProduces a single true if none of the results of the expression left of the operator are truthy.
sizeofLength of Each ValueOutputs the size of every result of the expression left of the operator. For collections this is the number of child elements. For strings, this is the length of the string.
countNumber of ValuesOutputs how many results were produced by the expression left of the operator.
emptyEmpty ResultsProduces a single true if the expression left of the operator produced no results.

Regular Expressions

Any regular expression can also be used as an operator. It executes against every string result to the left side of the RegExp, and outputs an array for each item containing the matching string and any capture groups, if the item matches.

Extending Operators

In addition to these built-ins, additional operators can be provided in the options of all of the base functions. See the src/operators.js file for an example of the structure of the operators object. Operators are provided as a keyed object where the key is the operator token and the value is an array of arguments:

  1. Operator Arity Type
  • -1: Prefix Unary, function will receive the results of the statement to the right of the operator.
  • 1: Postfix Unary, function will receive the results of the statement to the left of the operator.
  • 0: Binary, function will receive the results of the left and right statements as the first and second argument, respectively.
  • "r": N-ary, function operates as a reduction, with the first argument being the result of the previous execution, or first statement.
  1. Operator function. Receives either one or two arrays. Expected to return an array, even if it's empty.
  2. Precedence. Defaults to 0. Higher the number, higher the priority when lexing the path statement.