├── .eslintignore
├── .eslintrc.js
├── .gitattributes
├── .github
└── workflows
│ └── workflow.yaml
├── .gitignore
├── .prettierrc
├── LICENSE
├── README.md
├── package-lock.json
├── package.json
├── src
├── handler
│ ├── Handler.ts
│ ├── helper.ts
│ ├── paths.ts
│ └── query.ts
├── index.ts
└── parser
│ ├── Listener.ts
│ ├── errors.ts
│ ├── generated
│ ├── JSONPath.g4
│ ├── JSONPath.interp
│ ├── JSONPath.tokens
│ ├── JSONPathLexer.interp
│ ├── JSONPathLexer.js
│ ├── JSONPathLexer.tokens
│ ├── JSONPathListener.js
│ └── JSONPathParser.js
│ ├── parse.ts
│ ├── stringify.ts
│ └── types.ts
├── tests
├── consensus.test.ts
├── parse.test.ts
├── paths.test.ts
└── query.test.ts
├── tsconfig.json
└── webpack.config.js
/.eslintignore:
--------------------------------------------------------------------------------
1 | src/parser/generated/*
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | plugins: ['@typescript-eslint', 'prettier'],
4 | extends: ['plugin:@typescript-eslint/recommended'],
5 | rules: {
6 | 'no-console': 'error',
7 | '@typescript-eslint/no-explicit-any': 1,
8 | },
9 | };
10 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | src/parser/generated/*.js linguist-generated=true
--------------------------------------------------------------------------------
/.github/workflows/workflow.yaml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | jobs:
8 | build:
9 | runs-on: ubuntu-latest
10 |
11 | steps:
12 | - name: Checkout code
13 | uses: actions/checkout@v2
14 |
15 | - name: Setup Node.js
16 | uses: actions/setup-node@v2
17 | with:
18 | node-version: '12'
19 |
20 | - name: Restore cache
21 | uses: actions/cache@v4
22 | with:
23 | path: ~/.npm
24 | key: dependency-cache-${{ hashFiles('package-lock.json') }}
25 | restore-keys: |
26 | dependency-cache-${{ hashFiles('package-lock.json') }}
27 |
28 | - name: Install dependencies
29 | run: npm ci
30 |
31 | - name: Run tests
32 | run: npm run test
33 |
34 | - name: Store coverage artifacts
35 | uses: actions/upload-artifact@v4
36 | with:
37 | name: coverage
38 | path: coverage/
39 |
40 | - name: Upload coverage to Codecov
41 | uses: codecov/codecov-action@v1
42 | with:
43 | file: ./coverage/coverage-final.json
44 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | /dist
3 | coverage
4 | .DS_Store
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 120,
3 | "trailingComma": "all",
4 | "singleQuote": true
5 | }
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Antoine Tamano
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JsonPATHLY
2 |
3 |
4 |
5 | [](https://badge.fury.io/js/jsonpathly)
6 | [](https://codecov.io/gh/atamano/jsonpathly)
7 |
8 | **A secured and eval free typescript DSL for reading JSON documents.**
9 |
10 | [Link to the Demo](https://atamano.github.io/jsonpathly-demo/)
11 |
12 | ## Install
13 |
14 | Install from npm:
15 |
16 | ```bash
17 | $ npm install jsonpathly
18 | ```
19 |
20 | Install from yarn:
21 |
22 | ```bash
23 | $ yarn add jsonpathly
24 | ```
25 |
26 | ## Getting Started
27 |
28 | ```javascript
29 | import jp from "jsonpathly";
30 |
31 | const cities = [
32 | { name: "London", population: 8615246 },
33 | { name: "Berlin", population: 3517424 },
34 | { name: "Madrid", population: 3165235 },
35 | { name: "Rome", population: 2870528 },
36 | ];
37 |
38 | const names = jp.query(cities, "$..name");
39 |
40 | // [ "London", "Berlin", "Madrid", "Rome" ]
41 | ```
42 |
43 | JsonPath expressions are used to access elements in a JSON structure, similar to how XPath expressions are used with XML documents. The starting point in JsonPath is referred to as "$" and can be either an object or array.
44 |
45 | JsonPath expressions can use either dot notation, such as
46 |
47 | `$.store.book[0].title`
48 |
49 | or bracket notation, like
50 |
51 | `$['store']['book'][0]['title']`
52 |
53 | ## Operators
54 |
55 | The following table lists the available operators for JsonPath expressions:
56 |
57 | | Operator | Description |
58 | | :------------------------ | :-------------------------------------------------------------------------------- |
59 | | `$` | Refers to the root element of the JSON structure. It starts all path expressions. |
60 | | `@` | Refers to the current node being processed by a filter predicate. |
61 | | `*` | Acts as a wildcard, and can be used anywhere. |
62 | | `..` | Enables deep scanning, and can be used anywhere. A name is required. |
63 | | `.` | Refers to a dot-notated child element. |
64 | | `['' (, '')]` | Refers to bracket-notated child elements. |
65 | | `[ (, )]` | Refers to array index or indexes. |
66 | | `[start:end:step]` | A python-style array slicing operator. |
67 | | `[?()]` | A filter expression that must evaluate to a boolean value. |
68 |
69 | ## Filter Operators
70 |
71 | Filters are used to select specific elements from arrays based on logical expressions. The expression [?(@.age > 18)] filters items where the "age" property is greater than 18, with @ referring to the current item being processed. Complex filters can be created using the logical operators && and ||. When working with string literals, they must be surrounded by single or double quotes, such as [?(@.color == 'blue')] or [?(@.color == "blue")].
72 |
73 | The following table lists different operators and their descriptions:
74 |
75 | | Operator | Description |
76 | | :------- | :--------------------------------------------------------------------------------- |
77 | | == | left is equal to the right (note that 1 is not equal to '1') |
78 | | != | left is not equal to the right |
79 | | < | left is less than the right |
80 | | <= | left is less than or equal to the right |
81 | | > | left is greater than the right |
82 | | >= | left is greater than or equal to the right |
83 | | in | left exists in the right (e.g. `[?(@.size in ['S', 'M'])]`) |
84 | | nin | left does not exist in the right |
85 | | subsetof | left is a subset of the right (e.g. [?(@.sizes subsetof ['S', 'M', 'L'])]) |
86 | | anyof | left has items in common with the right (e.g. [?(@.sizes anyof ['M', 'L'])]) |
87 | | noneof | left has no items in common with the right (e.g. [?(@.sizes noneof ['M', 'L'])]) |
88 | | sizeof | size of the left must match the size of the right (both must be arrays or strings) |
89 | | size | size of the left must match the right (right must be a number) |
90 | | empty | left (array or string) must be empty |
91 |
92 | ## Methods
93 |
94 | #### jp.query(obj, pathExpression[, options])
95 |
96 | Used to find elements in the obj data that match the given pathExpression. The function returns an array of elements that match the expression or an empty array if none are found.
97 |
98 | ```javascript
99 | import jp from "jsonpathly";
100 |
101 | const players = jp.query(data, "$..players");
102 | // [ 'Nigel Short', 'Garry Kasparov', 'Vladimir Kramnik', 'Magnus Carlsen' ]
103 | ```
104 |
105 | | Option | Description |
106 | | :------------- | :---------------------------------------------------------------------- |
107 | | hideExceptions | Suppresses any exceptions that may be raised during the path evaluation |
108 | | returnArray | Forces array return |
109 |
110 | #### jp.paths(obj, pathExpression[, options])
111 |
112 | Get the paths to elements in obj that match pathExpression. The result is a list of paths to elements that fulfill the specified JSONPath expression.
113 |
114 | ```javascript
115 | const paths = jp.paths(data, "$..author");
116 | // [
117 | // '$["store"]["book"][0]["author"]',
118 | // '$["store"]["book"][1]["author"]',
119 | // '$["store"]["book"][2]["author"]',
120 | // '$["store"]["book"][3]["author"]'
121 | // ]
122 | ```
123 |
124 | | Option | Description |
125 | | :------------- | :------------------------------------------------------------------------ |
126 | | hideExceptions | This option ensures that no exceptions are thrown during path evaluation. |
127 |
128 | #### jp.parse(pathExpression[, options])
129 |
130 | Generates a structured tree representation of a JSONPath expression, with each node being of a specific type.
131 |
132 | ```javascript
133 | const tree = jp.parse("$..author");
134 | // { type: 'root', next: { type: 'subscript', value: { type: 'dotdot', value: { type: "identifier", value: "author" } } } }
135 | ```
136 |
137 | | Option | Description |
138 | | :------------- | :------------------------------------------------------------------------ |
139 | | hideExceptions | This option ensures that no exceptions are thrown during path evaluation. |
140 |
141 | #### jp.stringify(tree)
142 |
143 | Returns a jsonpath string from a tree representing jsonpath expression (jp.parse response)
144 |
145 | ```javascript
146 | const jsonpath = jp.stringify({
147 | type: "root",
148 | next: {
149 | type: "subscript",
150 | value: { type: "dotdot", value: { type: "identifier", value: "author" } },
151 | },
152 | });
153 | // "$..author"
154 | ```
155 |
156 | ## Differences from other javascript implementations
157 |
158 | Main reason you should use this library is for security and stability.
159 |
160 | #### Evaluating Expressions
161 |
162 | Script expressions (i.e., (...)) are disallowed to prevent XSS injections.
163 |
164 | Filter expressions (i.e., ?(...)) also avoid using eval or static-eval for security reasons.
165 |
166 | Instead, jsonpathly has its own parser and evaluator. For example, `$[(@.number +5 > $.otherNumber * 10 + 2)]`
167 | is valid, but
168 | `?(alert("hello"))` will produce a syntax error (which would trigger an alert in some JavaScript libraries).
169 |
170 | #### Grammar
171 |
172 | The project uses ANTLR [grammar](https://github.com/atamano/jsonpathly/blob/master/src/parser/generated/JSONPath.g4) to parse JSONPath expressions and construct a typed abstract syntax tree (AST).
173 |
174 | #### Implementation
175 |
176 | For an overview of jsonpathly implementations and to compare its differences with other libraries, you can visit https://cburgmer.github.io/json-path-comparison
177 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jsonpathly",
3 | "version": "2.0.3",
4 | "description": "Query json with jsonpath expressions",
5 | "browser": "dist/index.web.mjs",
6 | "main": "dist/index.node.cjs",
7 | "module": "dist/antlr4.node.mjs",
8 | "types": "dist/index.d.ts",
9 | "files": [
10 | "dist"
11 | ],
12 | "scripts": {
13 | "gen": "antlr4 -Dlanguage=JavaScript ./src/parser/generated/JSONPath.g4",
14 | "test": "mocha --require ts-node/register --timeout 60000 --exit --no-cache tests/*.ts",
15 | "build": "webpack",
16 | "format": "prettier --write \"src/**/*.ts\"",
17 | "lint": "eslint src --ext .ts",
18 | "prepare": "npm run build",
19 | "prepublishOnly": "npm test && npm run lint",
20 | "preversion": "npm run lint",
21 | "version": "npm run format && git add -A src",
22 | "postversion": "git push && git push --tags"
23 | },
24 | "repository": {
25 | "type": "git",
26 | "url": "https://github.com/atamano/jsonpathly.git"
27 | },
28 | "keywords": [
29 | "jsonpath",
30 | "typescript",
31 | "json",
32 | "path"
33 | ],
34 | "author": "Antoine Tamano",
35 | "license": "MIT",
36 | "bugs": {
37 | "url": "https://github.com/atamano/jsonpathly/issues"
38 | },
39 | "homepage": "https://github.com/atamano/jsonpathly#readme",
40 | "devDependencies": {
41 | "@types/chai": "^4.3.6",
42 | "@types/mocha": "^10.0.1",
43 | "@typescript-eslint/eslint-plugin": "^2.22.0",
44 | "@typescript-eslint/parser": "^2.22.0",
45 | "babel-eslint": "^10.1.0",
46 | "babel-loader": "8.2.3",
47 | "chai": "^4.3.8",
48 | "core-js": "^3.22.5",
49 | "eslint": "^6.8.0",
50 | "eslint-config-prettier": "^6.11.0",
51 | "eslint-plugin-prettier": "^3.1.3",
52 | "lint-staged": "^10.0.8",
53 | "mocha": "^10.2.0",
54 | "prettier": "^2.6.2",
55 | "ts-loader": "^9.4.4",
56 | "ts-node": "^10.9.1",
57 | "typescript": "^4.9.5",
58 | "webpack": "^5.88.2",
59 | "webpack-cli": "^5.1.4"
60 | },
61 | "dependencies": {
62 | "antlr4": "^4.13.2",
63 | "fast-deep-equal": "^3.1.3"
64 | },
65 | "exports": {
66 | ".": {
67 | "types": "./dist/index.d.ts",
68 | "node": {
69 | "types": "./dist/index.d.ts",
70 | "import": "./dist/index.node.mjs",
71 | "require": "./dist/index.node.cjs",
72 | "default": "./dist/index.node.mjs"
73 | },
74 | "browser": {
75 | "types": "./dist/index.d.ts",
76 | "import": "./dist/index.web.mjs",
77 | "require": "./dist/index.web.cjs",
78 | "default": "./dist/index.web.mjs"
79 | }
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/handler/Handler.ts:
--------------------------------------------------------------------------------
1 | import { JSONPathSyntaxError } from '../parser/errors';
2 | import {
3 | BracketExpressionContent,
4 | BracketMemberContent,
5 | Comparator,
6 | DotDot,
7 | FilterExpressionContent,
8 | Identifier,
9 | Indexes,
10 | LogicalExpression,
11 | NumericLiteral,
12 | OperationContent,
13 | Root,
14 | Slices,
15 | StringLiteral,
16 | Subscript,
17 | Unions,
18 | } from '../parser/types';
19 | import { isArray, isDefined, isEqual, isNumber, isPlainObject, isString, isUndefined } from './helper';
20 |
21 | const getNumericLiteralIndex = (index: number, total: number): number => (index < 0 ? total + index : index);
22 | const formatStringLiteralPath = (paths: string | string[], v: string): string | string[] => paths.concat(`["${v}"]`);
23 | const formatNumericLiteralPath = (paths: string | string[], v: number): string | string[] => paths.concat(`[${v}]`);
24 |
25 | type ValuePath = { value: T; paths: string | string[]; isIndefinite?: boolean };
26 |
27 | export class Handler {
28 | rootPayload: ValuePath;
29 |
30 | constructor(rootPayload: T) {
31 | this.rootPayload = { value: rootPayload, paths: '$' };
32 | }
33 |
34 | private handleIdentifier = (payload: ValuePath, tree: Identifier): ValuePath | undefined => {
35 | if (!isPlainObject(payload.value) || !(tree.value in payload.value)) {
36 | return;
37 | }
38 |
39 | return { value: payload.value[tree.value], paths: formatStringLiteralPath(payload.paths, tree.value) };
40 | };
41 |
42 | private handleWildcard = ({ value, paths }: ValuePath): ValuePath[] => {
43 | if (!isPlainObject(value) && !isArray(value)) {
44 | return [];
45 | }
46 |
47 | if (isArray(value)) {
48 | return value.map((item, index) => ({
49 | value: item,
50 | paths: formatNumericLiteralPath(paths, index),
51 | }));
52 | }
53 |
54 | return Object.keys(value).map((key) => ({ value: value[key], paths: formatStringLiteralPath(paths, key) }));
55 | };
56 |
57 | private handleOperationContent = (payload: ValuePath, tree: OperationContent): ValuePath | undefined => {
58 | switch (tree.type) {
59 | case 'root': {
60 | return this.handleSubscript(this.rootPayload, tree.next);
61 | }
62 | case 'current': {
63 | return this.handleSubscript(payload, tree.next);
64 | }
65 | case 'value': {
66 | return { value: tree.value, paths: payload.paths };
67 | }
68 | case 'groupOperation': {
69 | return this.handleOperationContent(payload, tree.value);
70 | }
71 | case 'operation': {
72 | const left = this.handleOperationContent(payload, tree.left)?.value;
73 | const right = this.handleOperationContent(payload, tree.right)?.value;
74 |
75 | if (!isNumber(left) || !isNumber(right)) {
76 | return;
77 | }
78 |
79 | switch (tree.operator) {
80 | case 'plus': {
81 | return { value: left + right, paths: payload.paths };
82 | }
83 | case 'minus': {
84 | return { value: left - right, paths: payload.paths };
85 | }
86 | case 'div': {
87 | if (right === 0) {
88 | return;
89 | }
90 | return { value: left / right, paths: payload.paths };
91 | }
92 | case 'multi': {
93 | return { value: left * right, paths: payload.paths };
94 | }
95 | case '': {
96 | if (right > 0) {
97 | throw new JSONPathSyntaxError(0, 0, 'Missing operator in operation');
98 | }
99 | return { value: left + right, paths: payload.paths };
100 | }
101 | }
102 | }
103 | }
104 | };
105 |
106 | private handleComparator = (payload: ValuePath, tree: Comparator): boolean => {
107 | const leftValue = this.handleOperationContent(payload, tree.left)?.value;
108 |
109 | if (tree.operator === 'empty') {
110 | if (!isArray(leftValue) && !isString(leftValue)) {
111 | return false;
112 | }
113 | return leftValue.length === 0;
114 | }
115 |
116 | const rightValue = this.handleOperationContent(payload, tree.right)?.value;
117 |
118 | switch (tree.operator) {
119 | case 'subsetof': {
120 | if (!isArray(leftValue) || !isArray(rightValue)) {
121 | return false;
122 | }
123 | const itemsRight = new Set(rightValue);
124 | return leftValue.every((e) => itemsRight.has(e));
125 | }
126 | case 'anyof': {
127 | if (!isArray(leftValue) || !isArray(rightValue)) {
128 | return false;
129 | }
130 | const itemsRight = new Set(rightValue);
131 | return leftValue.some((e) => itemsRight.has(e));
132 | }
133 | case 'noneof': {
134 | if (!isArray(leftValue) || !isArray(rightValue)) {
135 | return false;
136 | }
137 | const itemsRight = new Set(rightValue);
138 | return !leftValue.some((e) => itemsRight.has(e));
139 | }
140 | case 'sizeof': {
141 | if ((!isArray(leftValue) && !isString(leftValue)) || (!isArray(rightValue) && !isString(rightValue))) {
142 | return false;
143 | }
144 | return leftValue.length === rightValue.length;
145 | }
146 | case 'size': {
147 | if ((!isArray(leftValue) && !isString(leftValue)) || !isNumber(rightValue)) {
148 | return false;
149 | }
150 | return leftValue.length === rightValue;
151 | }
152 | case 'eq': {
153 | return isEqual(leftValue, rightValue);
154 | }
155 | case 'ne': {
156 | return !isEqual(leftValue, rightValue);
157 | }
158 | case 'lt': {
159 | if (isNumber(leftValue) && isNumber(rightValue)) {
160 | return leftValue < rightValue;
161 | }
162 | if (isString(leftValue) && isString(rightValue)) {
163 | return leftValue < rightValue;
164 | }
165 | return false;
166 | }
167 | case 'le': {
168 | if (isNumber(leftValue) && isNumber(rightValue)) {
169 | return leftValue <= rightValue;
170 | }
171 | if (isString(leftValue) && isString(rightValue)) {
172 | return leftValue <= rightValue;
173 | }
174 | return false;
175 | }
176 | case 'gt': {
177 | if (isNumber(leftValue) && isNumber(rightValue)) {
178 | return leftValue > rightValue;
179 | }
180 | if (isString(leftValue) && isString(rightValue)) {
181 | return leftValue > rightValue;
182 | }
183 | return false;
184 | }
185 | case 'ge': {
186 | if (isNumber(leftValue) && isNumber(rightValue)) {
187 | return leftValue >= rightValue;
188 | }
189 | if (isString(leftValue) && isString(rightValue)) {
190 | return leftValue >= rightValue;
191 | }
192 | return false;
193 | }
194 | case 'in': {
195 | if (!isArray(rightValue)) {
196 | return false;
197 | }
198 | return rightValue.includes(leftValue);
199 | }
200 | case 'nin': {
201 | if (!isArray(rightValue)) {
202 | return false;
203 | }
204 | return !rightValue.includes(leftValue);
205 | }
206 | case 'reg': {
207 | if (!isString(leftValue) || !isString(rightValue)) {
208 | return false;
209 | }
210 | const value = rightValue.slice(1, -1);
211 | return !!leftValue.match(new RegExp(value, tree.right.opts));
212 | }
213 | }
214 | };
215 |
216 | private handleLogicalExpression = (payload: ValuePath, tree: LogicalExpression): boolean => {
217 | const leftValue = this.handleFilterExpressionContent(payload, tree.left);
218 | const rightValue = this.handleFilterExpressionContent(payload, tree.right);
219 |
220 | switch (tree.operator) {
221 | case 'and': {
222 | return leftValue && rightValue;
223 | }
224 | case 'or': {
225 | return leftValue || rightValue;
226 | }
227 | }
228 | };
229 |
230 | private handleFilterExpressionContent = (payload: ValuePath, tree: FilterExpressionContent): boolean => {
231 | switch (tree.type) {
232 | case 'logicalExpression': {
233 | return this.handleLogicalExpression(payload, tree);
234 | }
235 | case 'comparator': {
236 | return this.handleComparator(payload, tree);
237 | }
238 | case 'groupExpression': {
239 | return this.handleFilterExpressionContent(payload, tree.value);
240 | }
241 | case 'notExpression': {
242 | return !this.handleFilterExpressionContent(payload, tree.value);
243 | }
244 | case 'root': {
245 | return isDefined(this.handleSubscript(this.rootPayload, tree.next));
246 | }
247 | case 'current': {
248 | return isDefined(this.handleSubscript(payload, tree.next));
249 | }
250 | case 'value': {
251 | return !!tree.value;
252 | }
253 | }
254 | };
255 |
256 | private handleNumericLiteral = ({ value, paths }: ValuePath, tree: NumericLiteral): ValuePath | undefined => {
257 | if (!isArray(value) && !isPlainObject(value)) {
258 | return;
259 | }
260 |
261 | if (isPlainObject(value)) {
262 | return this.handleStringLiteral({ value, paths }, { type: 'stringLiteral', value: `${tree.value}` });
263 | }
264 |
265 | const index = getNumericLiteralIndex(tree.value, value.length);
266 |
267 | if (index < value.length && index >= 0) {
268 | return { value: value[index], paths: formatNumericLiteralPath(paths, index) };
269 | }
270 | return;
271 | };
272 |
273 | private handleSlices = ({ value, paths }: ValuePath, tree: Slices): ValuePath[] => {
274 | const results: ValuePath[] = [];
275 |
276 | if (!isArray(value)) {
277 | return [];
278 | }
279 |
280 | const start = tree.start !== null ? getNumericLiteralIndex(tree.start, value.length) : 0;
281 | const end = tree.end !== null ? getNumericLiteralIndex(tree.end, value.length) : value.length;
282 | const step = tree.step === null || tree.step <= 0 ? 1 : tree.step;
283 |
284 | let count = 0;
285 | value.forEach((item, index) => {
286 | if (index >= start && index < end) {
287 | if (count % step === 0) {
288 | results.push({ value: item, paths: formatNumericLiteralPath(paths, index) });
289 | }
290 | count += 1;
291 | }
292 | });
293 |
294 | return results;
295 | };
296 |
297 | private handleStringLiteral = ({ value, paths }: ValuePath, tree: StringLiteral): ValuePath | undefined => {
298 | if (!isPlainObject(value) || !(tree.value in value)) {
299 | return;
300 | }
301 |
302 | return { value: value[tree.value], paths: formatStringLiteralPath(paths, tree.value) };
303 | };
304 |
305 | private handleUnions = (payload: ValuePath, tree: Unions): ValuePath[] => {
306 | if (!isPlainObject(payload.value)) {
307 | return [];
308 | }
309 |
310 | return tree.values
311 | .map((value) => {
312 | switch (value.type) {
313 | case 'identifier': {
314 | return this.handleIdentifier(payload, value);
315 | }
316 | case 'stringLiteral': {
317 | return this.handleStringLiteral(payload, value);
318 | }
319 | }
320 | })
321 | .filter(isDefined);
322 | };
323 |
324 | private handleIndexes = ({ value, paths }: ValuePath, tree: Indexes): ValuePath[] => {
325 | if (!isArray(value)) {
326 | return [];
327 | }
328 |
329 | return tree.values.map((item) => this.handleNumericLiteral({ value, paths }, item)).filter(isDefined);
330 | };
331 |
332 | private handleDotdot = (payload: ValuePath, tree: DotDot): ValuePath[] => {
333 | const treeValue = tree.value;
334 | const value = payload.value;
335 | let results: ValuePath[] = [];
336 |
337 | switch (treeValue.type) {
338 | case 'bracketMember': {
339 | const result = this.handleBracketMemberContent(payload, treeValue.value);
340 | if (isDefined(result)) {
341 | results = results.concat(result);
342 | }
343 | break;
344 | }
345 | case 'bracketExpression': {
346 | if (isPlainObject(value) || (isArray(value) && treeValue.value.type === 'wildcard')) {
347 | const result = this.handleBracketExpressionContent(payload, treeValue.value);
348 | results = results.concat(result);
349 | }
350 | break;
351 | }
352 | case 'wildcard': {
353 | const result = this.handleWildcard(payload);
354 | results = results.concat(result);
355 | break;
356 | }
357 | case 'identifier': {
358 | const result = this.handleIdentifier(payload, treeValue);
359 | if (isDefined(result)) {
360 | results = results.concat(result);
361 | }
362 | break;
363 | }
364 | }
365 |
366 | if (isPlainObject(value)) {
367 | Object.keys(value).forEach((key) => {
368 | const result = this.handleDotdot(
369 | { value: value[key], paths: formatStringLiteralPath(payload.paths, key) },
370 | tree,
371 | );
372 | results = results.concat(result);
373 | });
374 | } else if (isArray(value)) {
375 | value.forEach((item, index) => {
376 | const result = this.handleDotdot({ value: item, paths: formatNumericLiteralPath(payload.paths, index) }, tree);
377 | results = results.concat(result);
378 | });
379 | }
380 |
381 | return results;
382 | };
383 |
384 | private handleBracketMemberContent = (payload: ValuePath, tree: BracketMemberContent): ValuePath | undefined => {
385 | switch (tree.type) {
386 | case 'identifier': {
387 | return this.handleIdentifier(payload, tree);
388 | }
389 | case 'numericLiteral': {
390 | return this.handleNumericLiteral(payload, tree);
391 | }
392 | case 'stringLiteral': {
393 | return this.handleStringLiteral(payload, tree);
394 | }
395 | }
396 | };
397 |
398 | private handleBracketExpressionContent = (payload: ValuePath, tree: BracketExpressionContent): ValuePath[] => {
399 | const payloadValue = payload.value;
400 |
401 | switch (tree.type) {
402 | case 'filterExpression': {
403 | let results: ValuePath[] = [];
404 |
405 | if (isArray(payloadValue)) {
406 | payloadValue.forEach((value, index) => {
407 | const item = { value, paths: formatNumericLiteralPath(payload.paths, index) };
408 | if (this.handleFilterExpressionContent(item, tree.value)) {
409 | results = results.concat(item);
410 | }
411 | });
412 | } else if (isPlainObject(payloadValue)) {
413 | if (this.handleFilterExpressionContent(payload, tree.value)) {
414 | results = results.concat(payload);
415 | }
416 | }
417 |
418 | return results;
419 | }
420 | case 'indexes': {
421 | return this.handleIndexes(payload, tree);
422 | }
423 | case 'unions': {
424 | return this.handleUnions(payload, tree);
425 | }
426 | case 'wildcard': {
427 | return this.handleWildcard(payload);
428 | }
429 | case 'slices': {
430 | return this.handleSlices(payload, tree);
431 | }
432 | }
433 | };
434 |
435 | private concatIndefiniteValuePaths = (payload: ValuePath[], tree: Subscript | null): ValuePath => {
436 | if (!tree) {
437 | return payload.reduce>(
438 | (acc, current) => ({
439 | isIndefinite: true,
440 | value: [...acc.value, current.value],
441 | paths: [...acc.paths, current.paths] as string[],
442 | }),
443 | { value: [], paths: [], isIndefinite: true },
444 | );
445 | }
446 |
447 | let values: unknown[] = [];
448 | let paths: string[] = [];
449 |
450 | payload.forEach((item) => {
451 | const result = this.handleSubscript(item, tree);
452 |
453 | if (isUndefined(result)) {
454 | return;
455 | }
456 |
457 | values = result.isIndefinite ? values.concat(result.value) : [...values, result.value];
458 | paths = paths.concat(result.paths);
459 | });
460 |
461 | return { value: values, paths, isIndefinite: true };
462 | };
463 |
464 | private handleSubscript = (payload: ValuePath, tree: Subscript | null): ValuePath | undefined => {
465 | if (tree === null) {
466 | return payload;
467 | }
468 |
469 | const treeValue = tree.value;
470 | switch (treeValue.type) {
471 | case 'bracketExpression': {
472 | const result = this.handleBracketExpressionContent(payload, treeValue.value);
473 | return this.concatIndefiniteValuePaths(result, tree.next);
474 | }
475 | case 'bracketMember': {
476 | const result = this.handleBracketMemberContent(payload, treeValue.value);
477 | if (isUndefined(result)) {
478 | return;
479 | }
480 | return this.handleSubscript(result, tree.next);
481 | }
482 | case 'dot': {
483 | switch (treeValue.value.type) {
484 | case 'identifier': {
485 | const result = this.handleIdentifier(payload, treeValue.value);
486 | if (isUndefined(result)) {
487 | return;
488 | }
489 | return this.handleSubscript(result, tree.next);
490 | }
491 | case 'numericLiteral': {
492 | const result = this.handleNumericLiteral(payload, treeValue.value);
493 | if (isUndefined(result)) {
494 | return;
495 | }
496 | return this.handleSubscript(result, tree.next);
497 | }
498 | case 'wildcard': {
499 | const result = this.handleWildcard(payload);
500 | return this.concatIndefiniteValuePaths(result, tree.next);
501 | }
502 | }
503 | }
504 | case 'dotdot': {
505 | const result = this.handleDotdot(payload, treeValue);
506 | return this.concatIndefiniteValuePaths(result, tree.next);
507 | }
508 | }
509 | };
510 |
511 | public handleRoot = (tree: Root): ValuePath | undefined => {
512 | return this.handleSubscript(this.rootPayload, tree.next);
513 | };
514 | }
515 |
--------------------------------------------------------------------------------
/src/handler/helper.ts:
--------------------------------------------------------------------------------
1 | import * as equal from 'fast-deep-equal';
2 |
3 | export const isEqual = (objA: unknown, objB: unknown): boolean => {
4 | return equal(objA, objB);
5 | };
6 |
7 | export const isArray = (item: unknown): item is unknown[] => {
8 | return Array.isArray(item);
9 | };
10 |
11 | // https://github.com/reduxjs/redux/blob/master/src/utils/isPlainObject.ts
12 | export const isPlainObject = (item: unknown): item is Record => {
13 | if (typeof item !== 'object' || item === null) {
14 | return false;
15 | }
16 |
17 | let proto = item;
18 | while (Object.getPrototypeOf(proto) !== null) {
19 | proto = Object.getPrototypeOf(proto);
20 | }
21 |
22 | return Object.getPrototypeOf(item) === proto;
23 | };
24 |
25 | export const isNumber = (item: unknown): item is number => {
26 | return typeof item === 'number';
27 | };
28 |
29 | export const isString = (item: unknown): item is string => {
30 | return typeof item === 'string';
31 | };
32 |
33 | export const isUndefined = (item: T | undefined): item is undefined => {
34 | return typeof item === 'undefined';
35 | };
36 |
37 | export const isDefined = (item: T): item is Exclude => {
38 | return typeof item !== 'undefined';
39 | };
40 |
--------------------------------------------------------------------------------
/src/handler/paths.ts:
--------------------------------------------------------------------------------
1 | import { parseInternal } from '../parser/parse';
2 | import { Handler } from './Handler';
3 | import { isArray, isUndefined } from './helper';
4 |
5 | export type PathsOptions = {
6 | hideExceptions?: boolean;
7 | };
8 |
9 | export const paths = (payload: unknown, path: string, options: PathsOptions = {}): string[] => {
10 | try {
11 | const tree = parseInternal(path);
12 |
13 | const handler = new Handler(payload);
14 | const result = handler.handleRoot(tree);
15 |
16 | if (isUndefined(result)) {
17 | return [];
18 | }
19 |
20 | if (!isArray(result.paths)) {
21 | return [result.paths];
22 | }
23 | return result.paths;
24 | } catch (e) {
25 | if (!options.hideExceptions) {
26 | throw e;
27 | }
28 | return [];
29 | }
30 | };
31 |
--------------------------------------------------------------------------------
/src/handler/query.ts:
--------------------------------------------------------------------------------
1 | import { parseInternal } from '../parser/parse';
2 | import { Handler } from './Handler';
3 | import { isArray, isDefined, isUndefined } from './helper';
4 |
5 | export type QueryOptions = {
6 | hideExceptions?: boolean;
7 | returnArray?: boolean;
8 | };
9 |
10 | const querySingle = (payload: unknown, path: string, options: QueryOptions): unknown => {
11 | const tree = parseInternal(path);
12 |
13 | const handler = new Handler(payload);
14 | const result = handler.handleRoot(tree);
15 |
16 | if (!result?.isIndefinite && options.returnArray) {
17 | if (isUndefined(result)) {
18 | return [];
19 | }
20 | return [result.value];
21 | }
22 |
23 | return result?.value;
24 | };
25 |
26 | const queryMany = (payload: unknown, paths: string[], options: QueryOptions): unknown => {
27 | const results: unknown[] = [];
28 | for (const path of paths) {
29 | const res = querySingle(payload, path, options);
30 | if (isDefined(res)) {
31 | results.push(res);
32 | }
33 | }
34 | return results;
35 | };
36 |
37 | export const query = (payload: unknown, paths: string | string[], options: QueryOptions = {}): unknown => {
38 | try {
39 | if (isArray(paths)) {
40 | return queryMany(payload, paths, options);
41 | }
42 | return querySingle(payload, paths, options);
43 | } catch (e) {
44 | if (!options.hideExceptions) {
45 | throw e;
46 | }
47 |
48 | if (!!options.returnArray) {
49 | return [];
50 | }
51 | return;
52 | }
53 | };
54 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export { paths } from './handler/paths';
2 | export { query } from './handler/query';
3 |
4 | export { JSONPathSyntaxError } from './parser/errors';
5 | export { parse } from './parser/parse';
6 | export { stringify } from './parser/stringify';
7 |
--------------------------------------------------------------------------------
/src/parser/Listener.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-explicit-any */
2 | /* eslint-disable @typescript-eslint/no-unused-vars */
3 | /* eslint-disable @typescript-eslint/no-non-null-assertion */
4 |
5 | import JSONPathListener from './generated/JSONPathListener';
6 | import JSONPathParser from './generated/JSONPathParser';
7 | import {
8 | BracketExpression,
9 | BracketExpressionContent,
10 | BracketMember,
11 | BracketMemberContent,
12 | DotContent,
13 | DotDotContent,
14 | FilterExpression,
15 | Identifier,
16 | Indexes,
17 | JsonPathElement,
18 | NumericLiteral,
19 | OperationContent,
20 | Root,
21 | Slices,
22 | StringLiteral,
23 | Subscript,
24 | Unions,
25 | Value,
26 | ValueRegex,
27 | } from './types';
28 |
29 | const TYPE_CHECK_MAPPER = {
30 | root: (node: JsonPathElement): node is Root => 'type' in node && node.type === 'root',
31 | value: (node: JsonPathElement): node is Value => 'type' in node && node.type === 'value',
32 | regex: (node: JsonPathElement): node is ValueRegex =>
33 | 'type' in node && node.type === 'value' && node.subtype === 'regex',
34 | operationContent: (node: JsonPathElement): node is OperationContent =>
35 | 'type' in node &&
36 | typeof node.type === 'string' &&
37 | ['value', 'current', 'root', 'groupOperation', 'operation'].includes(node.type),
38 | subscript: (node: JsonPathElement): node is Subscript => 'type' in node && node.type === 'subscript',
39 | bracket: (node: JsonPathElement): node is BracketMember | BracketExpression =>
40 | 'type' in node && ['bracketMember', 'bracketExpression'].includes(node.type),
41 | unions: (node: JsonPathElement): node is Unions => 'type' in node && node.type === 'unions',
42 | indexes: (node: JsonPathElement): node is Indexes => 'type' in node && node.type === 'indexes',
43 | slices: (node: JsonPathElement): node is Slices => 'type' in node && node.type === 'slices',
44 | filterExpression: (node: JsonPathElement): node is FilterExpression =>
45 | 'type' in node && node.type === 'filterExpression',
46 | dotContent: (node: JsonPathElement): node is DotContent =>
47 | 'type' in node && ['identifier', 'numericLiteral', 'wildcard'].includes(node.type),
48 | dotdotContent: (node: JsonPathElement): node is DotDotContent =>
49 | 'type' in node && ['identifier', 'wildcard', 'bracketMember', 'bracketExpression'].includes(node.type),
50 | bracketContent: (node: JsonPathElement): node is BracketMemberContent | BracketExpressionContent =>
51 | 'type' in node &&
52 | [
53 | 'identifier',
54 | 'wildcard',
55 | 'numericLiteral',
56 | 'stringLiteral',
57 | 'filterExpression',
58 | 'slices',
59 | 'unions',
60 | 'indexes',
61 | ].includes(node.type),
62 | expressionContent: (node: JsonPathElement): node is FilterExpression['value'] =>
63 | 'type' in node &&
64 | ['value', 'comparator', 'groupExpression', 'logicalExpression', 'notExpression', 'current', 'root'].includes(
65 | node.type,
66 | ),
67 | } as const;
68 |
69 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
70 | type TypeGardReturn = K extends (a: any) => a is infer T ? T : never;
71 |
72 | const isBracketMember = (item: BracketMemberContent | BracketExpressionContent): item is BracketMemberContent =>
73 | ['identifier', 'numericLiteral', 'stringLiteral'].includes(item.type);
74 |
75 | export default class Listener extends JSONPathListener {
76 | _stack: JsonPathElement[] = [];
77 |
78 | public getTree(): Root {
79 | return this.popWithCheck('root', null);
80 | }
81 |
82 | private popWithCheck(
83 | key: T,
84 | ctx: any | null,
85 | ): TypeGardReturn {
86 | const value = this._stack.pop();
87 |
88 | if (typeof value !== 'undefined' && TYPE_CHECK_MAPPER[key](value)) {
89 | return value as TypeGardReturn;
90 | }
91 |
92 | /* istanbul ignore next */
93 | throw new Error(`bad type (${JSON.stringify(value)}) returned for ${key} with token: ${ctx?.getText()}`);
94 | }
95 |
96 | private push(node: JsonPathElement): void {
97 | this._stack.push(node);
98 | }
99 |
100 | public exitJsonpath(ctx: any): void {
101 | if (ctx.ROOT_VALUE()) {
102 | const next = ctx.subscript() ? this.popWithCheck('subscript', ctx) : null;
103 |
104 | this.push({ type: 'root', next });
105 | }
106 | }
107 |
108 | public exitBracketContent(ctx: any): void {
109 | switch (true) {
110 | case !!ctx.identifier(): {
111 | const text = ctx.identifier()!.getText();
112 |
113 | this.push({ type: 'identifier', value: text });
114 | break;
115 | }
116 | case !!ctx.STAR(): {
117 | this.push({ type: 'wildcard' });
118 | break;
119 | }
120 | case !!ctx.unions(): {
121 | const value = this.popWithCheck('unions', ctx);
122 |
123 | this.push(value);
124 | break;
125 | }
126 | case !!ctx.indexes(): {
127 | const value = this.popWithCheck('indexes', ctx);
128 |
129 | this.push(value);
130 | break;
131 | }
132 | case !!ctx.slices(): {
133 | const value = this.popWithCheck('slices', ctx);
134 |
135 | this.push(value);
136 | break;
137 | }
138 | case !!ctx.STRING(): {
139 | const value = ctx.STRING()!.getText().slice(1, -1);
140 |
141 | this.push({ type: 'stringLiteral', value });
142 | break;
143 | }
144 | case !!ctx.NUMBER(): {
145 | const number = Number.parseInt(ctx.NUMBER()!.getText());
146 |
147 | this.push({
148 | type: 'numericLiteral',
149 | value: number,
150 | });
151 | break;
152 | }
153 | case !!ctx.filterExpression(): {
154 | const value = this.popWithCheck('filterExpression', ctx);
155 |
156 | this.push(value);
157 | break;
158 | }
159 | }
160 | }
161 |
162 | public exitBracket(ctx: any): void {
163 | const value = this.popWithCheck('bracketContent', ctx);
164 |
165 | if (isBracketMember(value)) {
166 | this.push({
167 | type: 'bracketMember',
168 | value,
169 | });
170 | return;
171 | }
172 |
173 | this.push({
174 | type: 'bracketExpression',
175 | value,
176 | });
177 | }
178 |
179 | public exitDotdotContent(ctx: any): void {
180 | switch (true) {
181 | case !!ctx.STAR(): {
182 | this.push({ type: 'wildcard' });
183 | break;
184 | }
185 | case !!ctx.identifier(): {
186 | const value = ctx.identifier()!.getText();
187 |
188 | this.push({ type: 'identifier', value });
189 | break;
190 | }
191 | case !!ctx.bracket(): {
192 | const value = this.popWithCheck('bracket', ctx);
193 |
194 | this.push(value);
195 | break;
196 | }
197 | }
198 | }
199 |
200 | public exitDotContent(ctx: any): void {
201 | switch (true) {
202 | case !!ctx.STAR(): {
203 | this.push({ type: 'wildcard' });
204 | break;
205 | }
206 | case !!ctx.identifier(): {
207 | const text = ctx.identifier()!.getText();
208 |
209 | this.push({ type: 'identifier', value: text });
210 | break;
211 | }
212 | case !!ctx.NUMBER(): {
213 | const number = Number.parseInt(ctx.NUMBER()!.getText());
214 |
215 | this.push({
216 | type: 'numericLiteral',
217 | value: number,
218 | });
219 | break;
220 | }
221 | }
222 | }
223 |
224 | public exitSubscript(ctx: any): void {
225 | switch (true) {
226 | case !!ctx.DOT(): {
227 | const next = ctx.subscript() ? this.popWithCheck('subscript', ctx) : null;
228 | const value = this.popWithCheck('dotContent', ctx);
229 |
230 | this.push({
231 | type: 'subscript',
232 | value: {
233 | type: 'dot',
234 | value,
235 | },
236 | next,
237 | });
238 | break;
239 | }
240 | case !!ctx.DOTDOT(): {
241 | const next = ctx.subscript() ? this.popWithCheck('subscript', ctx) : null;
242 | const value = this.popWithCheck('dotdotContent', ctx);
243 |
244 | this.push({
245 | type: 'subscript',
246 | value: {
247 | type: 'dotdot',
248 | value,
249 | },
250 | next,
251 | });
252 | break;
253 | }
254 | case !!ctx.bracket(): {
255 | const next = ctx.subscript() ? this.popWithCheck('subscript', ctx) : null;
256 | const value = this.popWithCheck('bracket', ctx);
257 |
258 | this.push({
259 | type: 'subscript',
260 | next,
261 | value,
262 | });
263 | break;
264 | }
265 | }
266 | }
267 |
268 | public exitFilterpath(ctx: any): void {
269 | switch (true) {
270 | case !!ctx.ROOT_VALUE(): {
271 | const next = ctx.subscript() ? this.popWithCheck('subscript', ctx) : null;
272 |
273 | this.push({ type: 'root', next: next });
274 | break;
275 | }
276 | case !!ctx.CURRENT_VALUE(): {
277 | const next = ctx.subscript() ? this.popWithCheck('subscript', ctx) : null;
278 |
279 | this.push({ type: 'current', next: next });
280 | break;
281 | }
282 | }
283 | }
284 |
285 | public exitUnions(ctx: any): void {
286 | const nodes: (StringLiteral | Identifier)[] = [];
287 |
288 | for (let index = 0; index < ctx.identifier().length; index += 1) {
289 | const value = ctx.identifier(index)!.getText();
290 |
291 | nodes.push({
292 | type: 'identifier',
293 | value,
294 | });
295 | }
296 |
297 | for (let index = 0; index < ctx.STRING().length; index += 1) {
298 | const value = ctx.STRING(index)!.getText().slice(1, -1);
299 |
300 | nodes.push({
301 | type: 'stringLiteral',
302 | value,
303 | });
304 | }
305 |
306 | this.push({
307 | type: 'unions',
308 | values: nodes,
309 | });
310 | }
311 |
312 | public exitIndexes(ctx: any): void {
313 | const nodes: NumericLiteral[] = [];
314 |
315 | for (let index = 0; index < ctx.NUMBER().length; index += 1) {
316 | const number = Number.parseInt(ctx.NUMBER(index)!.getText());
317 |
318 | nodes.push({
319 | type: 'numericLiteral',
320 | value: number,
321 | });
322 | }
323 |
324 | this.push({
325 | type: 'indexes',
326 | values: nodes,
327 | });
328 | }
329 | public exitSlices(ctx: any): void {
330 | // Extract tokens
331 | const numbers = [0, 1, 2].map((index) => ctx.getToken(JSONPathParser.NUMBER, index));
332 | const colons = [0, 1].map((index) => ctx.getToken(JSONPathParser.COLON, index));
333 |
334 | let start: number | null = null;
335 | let end: number | null = null;
336 | let step: number | null = null;
337 |
338 | // Parse start value
339 | if (colons[0] && numbers[0] && numbers[0].getSourceInterval().start < colons[0].getSourceInterval().start) {
340 | start = Number.parseInt(numbers[0].getText());
341 | }
342 |
343 | // Parse end value
344 | if (
345 | !colons[1] &&
346 | colons[0] &&
347 | numbers[1] &&
348 | numbers[1].getSourceInterval().start > colons[0].getSourceInterval().start
349 | ) {
350 | end = Number.parseInt(numbers[1].getText());
351 | } else if (colons[1] && numbers[1] && numbers[1].getSourceInterval().start < colons[1].getSourceInterval().start) {
352 | end = Number.parseInt(numbers[1].getText());
353 | } else if (colons[0] && numbers[0] && numbers[0].getSourceInterval().start > colons[0].getSourceInterval().start) {
354 | if (!colons[1] || numbers[0].getSourceInterval().start < colons[1].getSourceInterval().start) {
355 | end = Number.parseInt(numbers[0].getText());
356 | }
357 | }
358 |
359 | // Parse step value
360 | if (colons[1] && numbers[2]) {
361 | step = Number.parseInt(numbers[2].getText());
362 | } else if (colons[1] && numbers[1] && numbers[1].getSourceInterval().start > colons[1].getSourceInterval().start) {
363 | step = Number.parseInt(numbers[1].getText());
364 | } else if (colons[1] && numbers[0] && numbers[0].getSourceInterval().start > colons[1].getSourceInterval().start) {
365 | step = Number.parseInt(numbers[0].getText());
366 | }
367 |
368 | // Push result
369 | this.push({ type: 'slices', start, end, step });
370 | }
371 |
372 | public exitFilterExpression(ctx: any): void {
373 | const value = this.popWithCheck('expressionContent', ctx);
374 |
375 | this.push({
376 | type: 'filterExpression',
377 | value,
378 | });
379 | }
380 |
381 | public exitRegex(ctx: any): void {
382 | const value = ctx.REGEX_EXPR().getText();
383 | const opts = ctx.REGEX_OPT()?.getText() || '';
384 |
385 | this.push({
386 | type: 'value',
387 | subtype: 'regex',
388 | value: value as ValueRegex['value'],
389 | opts,
390 | });
391 | }
392 |
393 | public exitExpression(ctx: any): void {
394 | switch (true) {
395 | case !!ctx.NOT(): {
396 | const value = this.popWithCheck('expressionContent', ctx);
397 |
398 | this.push({
399 | type: 'notExpression',
400 | value,
401 | });
402 | break;
403 | }
404 | case !!ctx.NULL(): {
405 | this.push({ type: 'value', value: null, subtype: 'null' });
406 | break;
407 | }
408 | case !!ctx.FALSE(): {
409 | this.push({ type: 'value', value: false, subtype: 'boolean' });
410 | break;
411 | }
412 | case !!ctx.TRUE(): {
413 | this.push({ type: 'value', value: true, subtype: 'boolean' });
414 | break;
415 | }
416 | case !!ctx.AND(): {
417 | const right = this.popWithCheck('expressionContent', ctx);
418 | const left = this.popWithCheck('expressionContent', ctx);
419 |
420 | this.push({ type: 'logicalExpression', operator: 'and', left, right });
421 | break;
422 | }
423 | case !!ctx.OR(): {
424 | const right = this.popWithCheck('expressionContent', ctx);
425 | const left = this.popWithCheck('expressionContent', ctx);
426 |
427 | this.push({ type: 'logicalExpression', operator: 'or', left, right });
428 | break;
429 | }
430 | case !!ctx.PAREN_LEFT(): {
431 | const value = this.popWithCheck('expressionContent', ctx);
432 |
433 | this.push({ type: 'groupExpression', value });
434 | break;
435 | }
436 | case !!ctx.regex(): {
437 | const right = this.popWithCheck('regex', ctx);
438 | const left = this.popWithCheck('operationContent', ctx);
439 |
440 | this.push({
441 | type: 'comparator',
442 | operator: 'reg',
443 | left,
444 | right,
445 | });
446 | break;
447 | }
448 | case !!ctx.EMPT(): {
449 | const left = this.popWithCheck('operationContent', ctx);
450 | this.push({ type: 'comparator', operator: 'empty', left, right: null });
451 | break;
452 | }
453 | case !!ctx.getTypedRuleContext(JSONPathParser.FilterargContext, 1): {
454 | const right = this.popWithCheck('operationContent', ctx);
455 | const left = this.popWithCheck('operationContent', ctx);
456 |
457 | switch (true) {
458 | case !!ctx.EQ(): {
459 | this.push({ type: 'comparator', operator: 'eq', left, right });
460 | break;
461 | }
462 | case !!ctx.NE(): {
463 | this.push({ type: 'comparator', operator: 'ne', left, right });
464 | break;
465 | }
466 | case !!ctx.LT(): {
467 | this.push({ type: 'comparator', operator: 'lt', left, right });
468 | break;
469 | }
470 | case !!ctx.LE(): {
471 | this.push({ type: 'comparator', operator: 'le', left, right });
472 | break;
473 | }
474 | case !!ctx.GT(): {
475 | this.push({ type: 'comparator', operator: 'gt', left, right });
476 | break;
477 | }
478 | case !!ctx.GE(): {
479 | this.push({ type: 'comparator', operator: 'ge', left, right });
480 | break;
481 | }
482 | case !!ctx.IN(): {
483 | this.push({ type: 'comparator', operator: 'in', left, right });
484 | break;
485 | }
486 | case !!ctx.NIN(): {
487 | this.push({ type: 'comparator', operator: 'nin', left, right });
488 | break;
489 | }
490 | case !!ctx.SUB(): {
491 | this.push({ type: 'comparator', operator: 'subsetof', left, right });
492 | break;
493 | }
494 | case !!ctx.ANY(): {
495 | this.push({ type: 'comparator', operator: 'anyof', left, right });
496 | break;
497 | }
498 | case !!ctx.NON(): {
499 | this.push({ type: 'comparator', operator: 'noneof', left, right });
500 | break;
501 | }
502 | case !!ctx.SIZ(): {
503 | this.push({ type: 'comparator', operator: 'size', left, right });
504 | break;
505 | }
506 | case !!ctx.SIZO(): {
507 | this.push({ type: 'comparator', operator: 'sizeof', left, right });
508 | break;
509 | }
510 | }
511 | break;
512 | }
513 | }
514 | }
515 |
516 | public exitObj(ctx: any): void {
517 | const obj: Record = {};
518 |
519 | for (const pairCtx of ctx.pair()) {
520 | const value = this.popWithCheck('value', ctx);
521 | const key = pairCtx.STRING().getText().slice(1, -1);
522 |
523 | obj[key] = value.value;
524 | }
525 |
526 | this.push({ type: 'value', subtype: 'object', value: obj });
527 | }
528 |
529 | public exitArray(ctx: any): void {
530 | const array: unknown[] = [];
531 |
532 | for (let index = 0; index < ctx.value().length; index += 1) {
533 | const value = this.popWithCheck('value', ctx);
534 |
535 | array.unshift(value.value);
536 | }
537 |
538 | this.push({ type: 'value', subtype: 'array', value: array });
539 | }
540 |
541 | public exitFilterarg(ctx: any): void {
542 | switch (true) {
543 | case !!ctx.getTypedRuleContext(JSONPathParser.FilterargContext, 1): {
544 | switch (true) {
545 | case !!ctx.STAR(): {
546 | const right = this.popWithCheck('operationContent', ctx);
547 | const left = this.popWithCheck('operationContent', ctx);
548 | this.push({ type: 'operation', operator: 'multi', left, right });
549 | break;
550 | }
551 | case !!ctx.DIV(): {
552 | const right = this.popWithCheck('operationContent', ctx);
553 | const left = this.popWithCheck('operationContent', ctx);
554 | this.push({ type: 'operation', operator: 'div', left, right });
555 | break;
556 | }
557 | case !!ctx.PLUS(): {
558 | const right = this.popWithCheck('operationContent', ctx);
559 | const left = this.popWithCheck('operationContent', ctx);
560 | this.push({ type: 'operation', operator: 'plus', left, right });
561 | break;
562 | }
563 | case !!ctx.MINUS_SP(): {
564 | const right = this.popWithCheck('operationContent', ctx);
565 | const left = this.popWithCheck('operationContent', ctx);
566 | this.push({ type: 'operation', operator: 'minus', left, right });
567 | break;
568 | }
569 | default: {
570 | // no operator occures when right value is negative, it should be validated at runtime
571 | const right = this.popWithCheck('operationContent', ctx);
572 | const left = this.popWithCheck('operationContent', ctx);
573 |
574 | this.push({ type: 'operation', operator: '', left, right });
575 | break;
576 | }
577 | }
578 | break;
579 | }
580 | case !!ctx.PAREN_LEFT(): {
581 | const value = this.popWithCheck('operationContent', ctx);
582 | this.push({ type: 'groupOperation', value });
583 | break;
584 | }
585 | case !!ctx.value(): {
586 | const left = this.popWithCheck('operationContent', ctx);
587 | this.push(left);
588 | break;
589 | }
590 | case !!ctx.filterpath(): {
591 | const value = this.popWithCheck('operationContent', ctx);
592 | this.push(value);
593 | break;
594 | }
595 | }
596 | }
597 |
598 | public exitValue(ctx: any): void {
599 | switch (true) {
600 | case !!ctx.STRING(): {
601 | const text = ctx.STRING()!.getText().slice(1, -1);
602 |
603 | this.push({ type: 'value', subtype: 'string', value: text });
604 | break;
605 | }
606 | case !!ctx.NUMBER(): {
607 | const text = ctx.NUMBER()!.getText();
608 |
609 | if (text !== `${Number.parseInt(text)}`) {
610 | this.push({ type: 'value', subtype: 'number', value: Number.parseFloat(text) });
611 | } else {
612 | this.push({ type: 'value', subtype: 'number', value: Number.parseInt(text) });
613 | }
614 | break;
615 | }
616 | case !!ctx.array():
617 | const value = this.popWithCheck('value', ctx);
618 | this.push(value);
619 | break;
620 | case !!ctx.obj(): {
621 | const value = this.popWithCheck('value', ctx);
622 | this.push(value);
623 | break;
624 | }
625 | case !!ctx.TRUE(): {
626 | this.push({ type: 'value', value: true, subtype: 'boolean' });
627 | break;
628 | }
629 | case !!ctx.FALSE(): {
630 | this.push({ type: 'value', value: false, subtype: 'boolean' });
631 | break;
632 | }
633 | case !!ctx.NULL(): {
634 | this.push({ type: 'value', value: null, subtype: 'null' });
635 | break;
636 | }
637 | }
638 | }
639 | }
640 |
--------------------------------------------------------------------------------
/src/parser/errors.ts:
--------------------------------------------------------------------------------
1 | export class JSONPathSyntaxError extends Error {
2 | line: number;
3 | charPositionInLine: number;
4 | msg: string;
5 |
6 | constructor(line: number, charPositionInLine: number, msg: string) {
7 | super(msg);
8 | this.line = line;
9 | this.charPositionInLine = charPositionInLine;
10 | this.msg = msg;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/parser/generated/JSONPath.g4:
--------------------------------------------------------------------------------
1 | grammar JSONPath;
2 |
3 | ////////////
4 | // TOKENS //
5 | ///////////
6 |
7 | CURRENT_VALUE : '@' ;
8 | DOTDOT : '..' ;
9 | ROOT_VALUE : '$' ;
10 | DOT : '.' ;
11 | STAR : '*' ;
12 |
13 | AND : '&&' ;
14 | EQ : '==' ;
15 | GE : '>=' ;
16 | GT : '>' ;
17 | LE : '<=' ;
18 | LT : '<' ;
19 | NE : '!=' ;
20 | REG : '=~' ;
21 | IN : ' in ' ;
22 | NIN : ' nin ' ;
23 | SUB : ' subsetof ' ;
24 | ANY : ' anyof ' ;
25 | NON : ' noneof ' ;
26 | SIZO : ' sizeof ' ;
27 | SIZ : ' size ' ;
28 | EMPT : ' empty' ;
29 | NOT : '!' ;
30 | OR : '||' ;
31 |
32 | TRUE : 'true' ;
33 | FALSE : 'false' ;
34 | NULL : 'null' ;
35 |
36 | BRACE_LEFT : '{' ;
37 | BRACE_RIGHT : '}' ;
38 | BRACKET_LEFT : '[' ;
39 | BRACKET_RIGHT : ']' ;
40 | COLON : ':' ;
41 | COMMA : ',' ;
42 | PAREN_LEFT : '(' ;
43 | PAREN_RIGHT : ')' ;
44 | QUESTION : '?' ;
45 |
46 | MINUS_SP: '- ';
47 | PLUS: '+';
48 | DIV: '/';
49 |
50 | REGEX_OPT: [gimsuy]*;
51 | REGEX_EXPR: '/'.*?'/';
52 | KEY: [a-zA-Z-_]*[a-zA-Z_][a-zA-Z0-9_]*;
53 | SPECIAL_KEY: [\u0080-\uFFFF_]+;
54 |
55 | WS
56 | : [ \t\n\r] + -> skip
57 | ;
58 |
59 | NUMBER
60 | : '-'? INT ('.' [0-9] +)? EXP?
61 | ;
62 |
63 | STRING
64 | : '"' (ESC_DOUBLE | SAFECODEPOINT_DOUBLE)* '"'
65 | | '\'' (ESC_SINGLE | SAFECODEPOINT_SINGLE)* '\''
66 | ;
67 |
68 | ///////////////
69 | // FRAGMENTS //
70 | //////////////
71 |
72 | fragment ESC_SINGLE
73 | : '\\' (['\\/bfnrt] | UNICODE)
74 | ;
75 |
76 | fragment ESC_DOUBLE
77 | : '\\' (["\\/bfnrt] | UNICODE)
78 | ;
79 |
80 | fragment UNICODE
81 | : 'u' HEX HEX HEX HEX
82 | ;
83 |
84 | fragment HEX
85 | : [0-9a-fA-F]
86 | ;
87 |
88 | fragment SAFECODEPOINT_SINGLE
89 | : ~ ['\\\u0000-\u001F]
90 | ;
91 |
92 | fragment SAFECODEPOINT_DOUBLE
93 | : ~ ["\\\u0000-\u001F]
94 | ;
95 |
96 | fragment INT
97 | : [0-9]+
98 | ;
99 | // with leading zeros
100 |
101 | fragment EXP
102 | : [Ee] [+\-]? INT
103 | ;
104 | // \- since - means "range" inside [...]
105 |
106 | /////////////
107 | // QUERIES //
108 | ////////////
109 |
110 | jsonpath
111 | : ROOT_VALUE subscript? EOF
112 | ;
113 |
114 | filterarg
115 | : PAREN_LEFT filterarg PAREN_RIGHT
116 | | filterarg ( STAR | DIV ) filterarg
117 | | filterarg ( PLUS | MINUS_SP )? filterarg
118 | | value
119 | | filterpath
120 | ;
121 |
122 | subscript
123 | : DOTDOT dotdotContent subscript?
124 | | DOT dotContent subscript?
125 | | bracket subscript?
126 | ;
127 |
128 | dotdotContent
129 | : STAR
130 | | identifier
131 | | bracket
132 | ;
133 |
134 | dotContent
135 | : STAR
136 | | NUMBER
137 | | identifier
138 | ;
139 |
140 | bracket
141 | : BRACKET_LEFT bracketContent BRACKET_RIGHT
142 | ;
143 |
144 | bracketContent
145 | : unions
146 | | indexes
147 | | slices
148 | | STAR
149 | | NUMBER
150 | | STRING
151 | | identifier
152 | | filterExpression
153 | ;
154 |
155 | filterExpression
156 | : QUESTION PAREN_LEFT expression PAREN_RIGHT
157 | ;
158 |
159 | indexes
160 | : NUMBER ( COMMA NUMBER )+
161 | ;
162 |
163 | unions
164 | : STRING ( COMMA STRING )+
165 | | identifier ( COMMA identifier )+
166 | ;
167 |
168 | slices
169 | : NUMBER? COLON NUMBER? ( COLON ( NUMBER )? )?
170 | ;
171 |
172 | regex : REGEX_EXPR REGEX_OPT?;
173 |
174 | expression
175 | : NOT PAREN_LEFT expression PAREN_RIGHT
176 | | PAREN_LEFT expression PAREN_RIGHT
177 | | expression ( AND | OR ) expression
178 | | filterarg ( EQ | NE | LT | LE | GT | GE | IN | NIN | SUB | ANY | SIZO| NON | SIZ ) filterarg
179 | | filterarg REG regex
180 | | filterarg EMPT
181 | | filterpath
182 | | TRUE
183 | | FALSE
184 | | NULL
185 | ;
186 |
187 | filterpath
188 | : ( ROOT_VALUE | CURRENT_VALUE ) subscript?
189 | ;
190 |
191 | identifier
192 | : KEY
193 | | SPECIAL_KEY
194 | | TRUE
195 | | FALSE
196 | | NULL
197 | ;
198 |
199 | obj
200 | : BRACE_LEFT pair ( COMMA pair )* BRACE_RIGHT
201 | | BRACE_LEFT BRACE_RIGHT
202 | ;
203 |
204 | pair
205 | : STRING COLON value
206 | ;
207 |
208 | array
209 | : BRACKET_LEFT value ( COMMA value )* BRACKET_RIGHT
210 | | BRACKET_LEFT BRACKET_RIGHT
211 | ;
212 |
213 | value
214 | : STRING
215 | | NUMBER
216 | | obj
217 | | array
218 | | TRUE
219 | | FALSE
220 | | NULL
221 | ;
222 |
223 |
--------------------------------------------------------------------------------
/src/parser/generated/JSONPath.interp:
--------------------------------------------------------------------------------
1 | token literal names:
2 | null
3 | '@'
4 | '..'
5 | '$'
6 | '.'
7 | '*'
8 | '&&'
9 | '=='
10 | '>='
11 | '>'
12 | '<='
13 | '<'
14 | '!='
15 | '=~'
16 | ' in '
17 | ' nin '
18 | ' subsetof '
19 | ' anyof '
20 | ' noneof '
21 | ' sizeof '
22 | ' size '
23 | ' empty'
24 | '!'
25 | '||'
26 | 'true'
27 | 'false'
28 | 'null'
29 | '{'
30 | '}'
31 | '['
32 | ']'
33 | ':'
34 | ','
35 | '('
36 | ')'
37 | '?'
38 | '- '
39 | '+'
40 | '/'
41 | null
42 | null
43 | null
44 | null
45 | null
46 | null
47 | null
48 |
49 | token symbolic names:
50 | null
51 | CURRENT_VALUE
52 | DOTDOT
53 | ROOT_VALUE
54 | DOT
55 | STAR
56 | AND
57 | EQ
58 | GE
59 | GT
60 | LE
61 | LT
62 | NE
63 | REG
64 | IN
65 | NIN
66 | SUB
67 | ANY
68 | NON
69 | SIZO
70 | SIZ
71 | EMPT
72 | NOT
73 | OR
74 | TRUE
75 | FALSE
76 | NULL
77 | BRACE_LEFT
78 | BRACE_RIGHT
79 | BRACKET_LEFT
80 | BRACKET_RIGHT
81 | COLON
82 | COMMA
83 | PAREN_LEFT
84 | PAREN_RIGHT
85 | QUESTION
86 | MINUS_SP
87 | PLUS
88 | DIV
89 | REGEX_OPT
90 | REGEX_EXPR
91 | KEY
92 | SPECIAL_KEY
93 | WS
94 | NUMBER
95 | STRING
96 |
97 | rule names:
98 | jsonpath
99 | filterarg
100 | subscript
101 | dotdotContent
102 | dotContent
103 | bracket
104 | bracketContent
105 | filterExpression
106 | indexes
107 | unions
108 | slices
109 | regex
110 | expression
111 | filterpath
112 | identifier
113 | obj
114 | pair
115 | array
116 | value
117 |
118 |
119 | atn:
120 | [4, 1, 45, 236, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 1, 0, 1, 0, 3, 0, 41, 8, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 52, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 59, 8, 1, 1, 1, 5, 1, 62, 8, 1, 10, 1, 12, 1, 65, 9, 1, 1, 2, 1, 2, 1, 2, 3, 2, 70, 8, 2, 1, 2, 1, 2, 1, 2, 3, 2, 75, 8, 2, 1, 2, 1, 2, 3, 2, 79, 8, 2, 3, 2, 81, 8, 2, 1, 3, 1, 3, 1, 3, 3, 3, 86, 8, 3, 1, 4, 1, 4, 1, 4, 3, 4, 91, 8, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 3, 6, 105, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 4, 8, 115, 8, 8, 11, 8, 12, 8, 116, 1, 9, 1, 9, 1, 9, 4, 9, 122, 8, 9, 11, 9, 12, 9, 123, 1, 9, 1, 9, 1, 9, 4, 9, 129, 8, 9, 11, 9, 12, 9, 130, 3, 9, 133, 8, 9, 1, 10, 3, 10, 136, 8, 10, 1, 10, 1, 10, 3, 10, 140, 8, 10, 1, 10, 1, 10, 3, 10, 144, 8, 10, 3, 10, 146, 8, 10, 1, 11, 1, 11, 3, 11, 150, 8, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 3, 12, 177, 8, 12, 1, 12, 1, 12, 1, 12, 5, 12, 182, 8, 12, 10, 12, 12, 12, 185, 9, 12, 1, 13, 1, 13, 3, 13, 189, 8, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 5, 15, 197, 8, 15, 10, 15, 12, 15, 200, 9, 15, 1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 206, 8, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 5, 17, 216, 8, 17, 10, 17, 12, 17, 219, 9, 17, 1, 17, 1, 17, 1, 17, 1, 17, 3, 17, 225, 8, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 3, 18, 234, 8, 18, 1, 18, 0, 2, 2, 24, 19, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 0, 6, 2, 0, 5, 5, 38, 38, 1, 0, 36, 37, 2, 0, 7, 12, 14, 20, 2, 0, 6, 6, 23, 23, 2, 0, 1, 1, 3, 3, 2, 0, 24, 26, 41, 42, 267, 0, 38, 1, 0, 0, 0, 2, 51, 1, 0, 0, 0, 4, 80, 1, 0, 0, 0, 6, 85, 1, 0, 0, 0, 8, 90, 1, 0, 0, 0, 10, 92, 1, 0, 0, 0, 12, 104, 1, 0, 0, 0, 14, 106, 1, 0, 0, 0, 16, 111, 1, 0, 0, 0, 18, 132, 1, 0, 0, 0, 20, 135, 1, 0, 0, 0, 22, 147, 1, 0, 0, 0, 24, 176, 1, 0, 0, 0, 26, 186, 1, 0, 0, 0, 28, 190, 1, 0, 0, 0, 30, 205, 1, 0, 0, 0, 32, 207, 1, 0, 0, 0, 34, 224, 1, 0, 0, 0, 36, 233, 1, 0, 0, 0, 38, 40, 5, 3, 0, 0, 39, 41, 3, 4, 2, 0, 40, 39, 1, 0, 0, 0, 40, 41, 1, 0, 0, 0, 41, 42, 1, 0, 0, 0, 42, 43, 5, 0, 0, 1, 43, 1, 1, 0, 0, 0, 44, 45, 6, 1, -1, 0, 45, 46, 5, 33, 0, 0, 46, 47, 3, 2, 1, 0, 47, 48, 5, 34, 0, 0, 48, 52, 1, 0, 0, 0, 49, 52, 3, 36, 18, 0, 50, 52, 3, 26, 13, 0, 51, 44, 1, 0, 0, 0, 51, 49, 1, 0, 0, 0, 51, 50, 1, 0, 0, 0, 52, 63, 1, 0, 0, 0, 53, 54, 10, 4, 0, 0, 54, 55, 7, 0, 0, 0, 55, 62, 3, 2, 1, 5, 56, 58, 10, 3, 0, 0, 57, 59, 7, 1, 0, 0, 58, 57, 1, 0, 0, 0, 58, 59, 1, 0, 0, 0, 59, 60, 1, 0, 0, 0, 60, 62, 3, 2, 1, 4, 61, 53, 1, 0, 0, 0, 61, 56, 1, 0, 0, 0, 62, 65, 1, 0, 0, 0, 63, 61, 1, 0, 0, 0, 63, 64, 1, 0, 0, 0, 64, 3, 1, 0, 0, 0, 65, 63, 1, 0, 0, 0, 66, 67, 5, 2, 0, 0, 67, 69, 3, 6, 3, 0, 68, 70, 3, 4, 2, 0, 69, 68, 1, 0, 0, 0, 69, 70, 1, 0, 0, 0, 70, 81, 1, 0, 0, 0, 71, 72, 5, 4, 0, 0, 72, 74, 3, 8, 4, 0, 73, 75, 3, 4, 2, 0, 74, 73, 1, 0, 0, 0, 74, 75, 1, 0, 0, 0, 75, 81, 1, 0, 0, 0, 76, 78, 3, 10, 5, 0, 77, 79, 3, 4, 2, 0, 78, 77, 1, 0, 0, 0, 78, 79, 1, 0, 0, 0, 79, 81, 1, 0, 0, 0, 80, 66, 1, 0, 0, 0, 80, 71, 1, 0, 0, 0, 80, 76, 1, 0, 0, 0, 81, 5, 1, 0, 0, 0, 82, 86, 5, 5, 0, 0, 83, 86, 3, 28, 14, 0, 84, 86, 3, 10, 5, 0, 85, 82, 1, 0, 0, 0, 85, 83, 1, 0, 0, 0, 85, 84, 1, 0, 0, 0, 86, 7, 1, 0, 0, 0, 87, 91, 5, 5, 0, 0, 88, 91, 5, 44, 0, 0, 89, 91, 3, 28, 14, 0, 90, 87, 1, 0, 0, 0, 90, 88, 1, 0, 0, 0, 90, 89, 1, 0, 0, 0, 91, 9, 1, 0, 0, 0, 92, 93, 5, 29, 0, 0, 93, 94, 3, 12, 6, 0, 94, 95, 5, 30, 0, 0, 95, 11, 1, 0, 0, 0, 96, 105, 3, 18, 9, 0, 97, 105, 3, 16, 8, 0, 98, 105, 3, 20, 10, 0, 99, 105, 5, 5, 0, 0, 100, 105, 5, 44, 0, 0, 101, 105, 5, 45, 0, 0, 102, 105, 3, 28, 14, 0, 103, 105, 3, 14, 7, 0, 104, 96, 1, 0, 0, 0, 104, 97, 1, 0, 0, 0, 104, 98, 1, 0, 0, 0, 104, 99, 1, 0, 0, 0, 104, 100, 1, 0, 0, 0, 104, 101, 1, 0, 0, 0, 104, 102, 1, 0, 0, 0, 104, 103, 1, 0, 0, 0, 105, 13, 1, 0, 0, 0, 106, 107, 5, 35, 0, 0, 107, 108, 5, 33, 0, 0, 108, 109, 3, 24, 12, 0, 109, 110, 5, 34, 0, 0, 110, 15, 1, 0, 0, 0, 111, 114, 5, 44, 0, 0, 112, 113, 5, 32, 0, 0, 113, 115, 5, 44, 0, 0, 114, 112, 1, 0, 0, 0, 115, 116, 1, 0, 0, 0, 116, 114, 1, 0, 0, 0, 116, 117, 1, 0, 0, 0, 117, 17, 1, 0, 0, 0, 118, 121, 5, 45, 0, 0, 119, 120, 5, 32, 0, 0, 120, 122, 5, 45, 0, 0, 121, 119, 1, 0, 0, 0, 122, 123, 1, 0, 0, 0, 123, 121, 1, 0, 0, 0, 123, 124, 1, 0, 0, 0, 124, 133, 1, 0, 0, 0, 125, 128, 3, 28, 14, 0, 126, 127, 5, 32, 0, 0, 127, 129, 3, 28, 14, 0, 128, 126, 1, 0, 0, 0, 129, 130, 1, 0, 0, 0, 130, 128, 1, 0, 0, 0, 130, 131, 1, 0, 0, 0, 131, 133, 1, 0, 0, 0, 132, 118, 1, 0, 0, 0, 132, 125, 1, 0, 0, 0, 133, 19, 1, 0, 0, 0, 134, 136, 5, 44, 0, 0, 135, 134, 1, 0, 0, 0, 135, 136, 1, 0, 0, 0, 136, 137, 1, 0, 0, 0, 137, 139, 5, 31, 0, 0, 138, 140, 5, 44, 0, 0, 139, 138, 1, 0, 0, 0, 139, 140, 1, 0, 0, 0, 140, 145, 1, 0, 0, 0, 141, 143, 5, 31, 0, 0, 142, 144, 5, 44, 0, 0, 143, 142, 1, 0, 0, 0, 143, 144, 1, 0, 0, 0, 144, 146, 1, 0, 0, 0, 145, 141, 1, 0, 0, 0, 145, 146, 1, 0, 0, 0, 146, 21, 1, 0, 0, 0, 147, 149, 5, 40, 0, 0, 148, 150, 5, 39, 0, 0, 149, 148, 1, 0, 0, 0, 149, 150, 1, 0, 0, 0, 150, 23, 1, 0, 0, 0, 151, 152, 6, 12, -1, 0, 152, 153, 5, 22, 0, 0, 153, 154, 5, 33, 0, 0, 154, 155, 3, 24, 12, 0, 155, 156, 5, 34, 0, 0, 156, 177, 1, 0, 0, 0, 157, 158, 5, 33, 0, 0, 158, 159, 3, 24, 12, 0, 159, 160, 5, 34, 0, 0, 160, 177, 1, 0, 0, 0, 161, 162, 3, 2, 1, 0, 162, 163, 7, 2, 0, 0, 163, 164, 3, 2, 1, 0, 164, 177, 1, 0, 0, 0, 165, 166, 3, 2, 1, 0, 166, 167, 5, 13, 0, 0, 167, 168, 3, 22, 11, 0, 168, 177, 1, 0, 0, 0, 169, 170, 3, 2, 1, 0, 170, 171, 5, 21, 0, 0, 171, 177, 1, 0, 0, 0, 172, 177, 3, 26, 13, 0, 173, 177, 5, 24, 0, 0, 174, 177, 5, 25, 0, 0, 175, 177, 5, 26, 0, 0, 176, 151, 1, 0, 0, 0, 176, 157, 1, 0, 0, 0, 176, 161, 1, 0, 0, 0, 176, 165, 1, 0, 0, 0, 176, 169, 1, 0, 0, 0, 176, 172, 1, 0, 0, 0, 176, 173, 1, 0, 0, 0, 176, 174, 1, 0, 0, 0, 176, 175, 1, 0, 0, 0, 177, 183, 1, 0, 0, 0, 178, 179, 10, 8, 0, 0, 179, 180, 7, 3, 0, 0, 180, 182, 3, 24, 12, 9, 181, 178, 1, 0, 0, 0, 182, 185, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 183, 184, 1, 0, 0, 0, 184, 25, 1, 0, 0, 0, 185, 183, 1, 0, 0, 0, 186, 188, 7, 4, 0, 0, 187, 189, 3, 4, 2, 0, 188, 187, 1, 0, 0, 0, 188, 189, 1, 0, 0, 0, 189, 27, 1, 0, 0, 0, 190, 191, 7, 5, 0, 0, 191, 29, 1, 0, 0, 0, 192, 193, 5, 27, 0, 0, 193, 198, 3, 32, 16, 0, 194, 195, 5, 32, 0, 0, 195, 197, 3, 32, 16, 0, 196, 194, 1, 0, 0, 0, 197, 200, 1, 0, 0, 0, 198, 196, 1, 0, 0, 0, 198, 199, 1, 0, 0, 0, 199, 201, 1, 0, 0, 0, 200, 198, 1, 0, 0, 0, 201, 202, 5, 28, 0, 0, 202, 206, 1, 0, 0, 0, 203, 204, 5, 27, 0, 0, 204, 206, 5, 28, 0, 0, 205, 192, 1, 0, 0, 0, 205, 203, 1, 0, 0, 0, 206, 31, 1, 0, 0, 0, 207, 208, 5, 45, 0, 0, 208, 209, 5, 31, 0, 0, 209, 210, 3, 36, 18, 0, 210, 33, 1, 0, 0, 0, 211, 212, 5, 29, 0, 0, 212, 217, 3, 36, 18, 0, 213, 214, 5, 32, 0, 0, 214, 216, 3, 36, 18, 0, 215, 213, 1, 0, 0, 0, 216, 219, 1, 0, 0, 0, 217, 215, 1, 0, 0, 0, 217, 218, 1, 0, 0, 0, 218, 220, 1, 0, 0, 0, 219, 217, 1, 0, 0, 0, 220, 221, 5, 30, 0, 0, 221, 225, 1, 0, 0, 0, 222, 223, 5, 29, 0, 0, 223, 225, 5, 30, 0, 0, 224, 211, 1, 0, 0, 0, 224, 222, 1, 0, 0, 0, 225, 35, 1, 0, 0, 0, 226, 234, 5, 45, 0, 0, 227, 234, 5, 44, 0, 0, 228, 234, 3, 30, 15, 0, 229, 234, 3, 34, 17, 0, 230, 234, 5, 24, 0, 0, 231, 234, 5, 25, 0, 0, 232, 234, 5, 26, 0, 0, 233, 226, 1, 0, 0, 0, 233, 227, 1, 0, 0, 0, 233, 228, 1, 0, 0, 0, 233, 229, 1, 0, 0, 0, 233, 230, 1, 0, 0, 0, 233, 231, 1, 0, 0, 0, 233, 232, 1, 0, 0, 0, 234, 37, 1, 0, 0, 0, 29, 40, 51, 58, 61, 63, 69, 74, 78, 80, 85, 90, 104, 116, 123, 130, 132, 135, 139, 143, 145, 149, 176, 183, 188, 198, 205, 217, 224, 233]
--------------------------------------------------------------------------------
/src/parser/generated/JSONPath.tokens:
--------------------------------------------------------------------------------
1 | CURRENT_VALUE=1
2 | DOTDOT=2
3 | ROOT_VALUE=3
4 | DOT=4
5 | STAR=5
6 | AND=6
7 | EQ=7
8 | GE=8
9 | GT=9
10 | LE=10
11 | LT=11
12 | NE=12
13 | REG=13
14 | IN=14
15 | NIN=15
16 | SUB=16
17 | ANY=17
18 | NON=18
19 | SIZO=19
20 | SIZ=20
21 | EMPT=21
22 | NOT=22
23 | OR=23
24 | TRUE=24
25 | FALSE=25
26 | NULL=26
27 | BRACE_LEFT=27
28 | BRACE_RIGHT=28
29 | BRACKET_LEFT=29
30 | BRACKET_RIGHT=30
31 | COLON=31
32 | COMMA=32
33 | PAREN_LEFT=33
34 | PAREN_RIGHT=34
35 | QUESTION=35
36 | MINUS_SP=36
37 | PLUS=37
38 | DIV=38
39 | REGEX_OPT=39
40 | REGEX_EXPR=40
41 | KEY=41
42 | SPECIAL_KEY=42
43 | WS=43
44 | NUMBER=44
45 | STRING=45
46 | '@'=1
47 | '..'=2
48 | '$'=3
49 | '.'=4
50 | '*'=5
51 | '&&'=6
52 | '=='=7
53 | '>='=8
54 | '>'=9
55 | '<='=10
56 | '<'=11
57 | '!='=12
58 | '=~'=13
59 | ' in '=14
60 | ' nin '=15
61 | ' subsetof '=16
62 | ' anyof '=17
63 | ' noneof '=18
64 | ' sizeof '=19
65 | ' size '=20
66 | ' empty'=21
67 | '!'=22
68 | '||'=23
69 | 'true'=24
70 | 'false'=25
71 | 'null'=26
72 | '{'=27
73 | '}'=28
74 | '['=29
75 | ']'=30
76 | ':'=31
77 | ','=32
78 | '('=33
79 | ')'=34
80 | '?'=35
81 | '- '=36
82 | '+'=37
83 | '/'=38
84 |
--------------------------------------------------------------------------------
/src/parser/generated/JSONPathLexer.interp:
--------------------------------------------------------------------------------
1 | token literal names:
2 | null
3 | '@'
4 | '..'
5 | '$'
6 | '.'
7 | '*'
8 | '&&'
9 | '=='
10 | '>='
11 | '>'
12 | '<='
13 | '<'
14 | '!='
15 | '=~'
16 | ' in '
17 | ' nin '
18 | ' subsetof '
19 | ' anyof '
20 | ' noneof '
21 | ' sizeof '
22 | ' size '
23 | ' empty'
24 | '!'
25 | '||'
26 | 'true'
27 | 'false'
28 | 'null'
29 | '{'
30 | '}'
31 | '['
32 | ']'
33 | ':'
34 | ','
35 | '('
36 | ')'
37 | '?'
38 | '- '
39 | '+'
40 | '/'
41 | null
42 | null
43 | null
44 | null
45 | null
46 | null
47 | null
48 |
49 | token symbolic names:
50 | null
51 | CURRENT_VALUE
52 | DOTDOT
53 | ROOT_VALUE
54 | DOT
55 | STAR
56 | AND
57 | EQ
58 | GE
59 | GT
60 | LE
61 | LT
62 | NE
63 | REG
64 | IN
65 | NIN
66 | SUB
67 | ANY
68 | NON
69 | SIZO
70 | SIZ
71 | EMPT
72 | NOT
73 | OR
74 | TRUE
75 | FALSE
76 | NULL
77 | BRACE_LEFT
78 | BRACE_RIGHT
79 | BRACKET_LEFT
80 | BRACKET_RIGHT
81 | COLON
82 | COMMA
83 | PAREN_LEFT
84 | PAREN_RIGHT
85 | QUESTION
86 | MINUS_SP
87 | PLUS
88 | DIV
89 | REGEX_OPT
90 | REGEX_EXPR
91 | KEY
92 | SPECIAL_KEY
93 | WS
94 | NUMBER
95 | STRING
96 |
97 | rule names:
98 | CURRENT_VALUE
99 | DOTDOT
100 | ROOT_VALUE
101 | DOT
102 | STAR
103 | AND
104 | EQ
105 | GE
106 | GT
107 | LE
108 | LT
109 | NE
110 | REG
111 | IN
112 | NIN
113 | SUB
114 | ANY
115 | NON
116 | SIZO
117 | SIZ
118 | EMPT
119 | NOT
120 | OR
121 | TRUE
122 | FALSE
123 | NULL
124 | BRACE_LEFT
125 | BRACE_RIGHT
126 | BRACKET_LEFT
127 | BRACKET_RIGHT
128 | COLON
129 | COMMA
130 | PAREN_LEFT
131 | PAREN_RIGHT
132 | QUESTION
133 | MINUS_SP
134 | PLUS
135 | DIV
136 | REGEX_OPT
137 | REGEX_EXPR
138 | KEY
139 | SPECIAL_KEY
140 | WS
141 | NUMBER
142 | STRING
143 | ESC_SINGLE
144 | ESC_DOUBLE
145 | UNICODE
146 | HEX
147 | SAFECODEPOINT_SINGLE
148 | SAFECODEPOINT_DOUBLE
149 | INT
150 | EXP
151 |
152 | channel names:
153 | DEFAULT_TOKEN_CHANNEL
154 | HIDDEN
155 |
156 | mode names:
157 | DEFAULT_MODE
158 |
159 | atn:
160 | [4, 0, 45, 356, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 37, 1, 37, 1, 38, 5, 38, 250, 8, 38, 10, 38, 12, 38, 253, 9, 38, 1, 39, 1, 39, 5, 39, 257, 8, 39, 10, 39, 12, 39, 260, 9, 39, 1, 39, 1, 39, 1, 40, 5, 40, 265, 8, 40, 10, 40, 12, 40, 268, 9, 40, 1, 40, 1, 40, 5, 40, 272, 8, 40, 10, 40, 12, 40, 275, 9, 40, 1, 41, 4, 41, 278, 8, 41, 11, 41, 12, 41, 279, 1, 42, 4, 42, 283, 8, 42, 11, 42, 12, 42, 284, 1, 42, 1, 42, 1, 43, 3, 43, 290, 8, 43, 1, 43, 1, 43, 1, 43, 4, 43, 295, 8, 43, 11, 43, 12, 43, 296, 3, 43, 299, 8, 43, 1, 43, 3, 43, 302, 8, 43, 1, 44, 1, 44, 1, 44, 5, 44, 307, 8, 44, 10, 44, 12, 44, 310, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 316, 8, 44, 10, 44, 12, 44, 319, 9, 44, 1, 44, 3, 44, 322, 8, 44, 1, 45, 1, 45, 1, 45, 3, 45, 327, 8, 45, 1, 46, 1, 46, 1, 46, 3, 46, 332, 8, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 49, 1, 49, 1, 50, 1, 50, 1, 51, 4, 51, 347, 8, 51, 11, 51, 12, 51, 348, 1, 52, 1, 52, 3, 52, 353, 8, 52, 1, 52, 1, 52, 1, 258, 0, 53, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, 43, 87, 44, 89, 45, 91, 0, 93, 0, 95, 0, 97, 0, 99, 0, 101, 0, 103, 0, 105, 0, 1, 0, 14, 6, 0, 103, 103, 105, 105, 109, 109, 115, 115, 117, 117, 121, 121, 4, 0, 45, 45, 65, 90, 95, 95, 97, 122, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, 122, 2, 0, 95, 95, 128, 65535, 3, 0, 9, 10, 13, 13, 32, 32, 1, 0, 48, 57, 8, 0, 39, 39, 47, 47, 92, 92, 98, 98, 102, 102, 110, 110, 114, 114, 116, 116, 8, 0, 34, 34, 47, 47, 92, 92, 98, 98, 102, 102, 110, 110, 114, 114, 116, 116, 3, 0, 48, 57, 65, 70, 97, 102, 3, 0, 0, 31, 39, 39, 92, 92, 3, 0, 0, 31, 34, 34, 92, 92, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 366, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 1, 107, 1, 0, 0, 0, 3, 109, 1, 0, 0, 0, 5, 112, 1, 0, 0, 0, 7, 114, 1, 0, 0, 0, 9, 116, 1, 0, 0, 0, 11, 118, 1, 0, 0, 0, 13, 121, 1, 0, 0, 0, 15, 124, 1, 0, 0, 0, 17, 127, 1, 0, 0, 0, 19, 129, 1, 0, 0, 0, 21, 132, 1, 0, 0, 0, 23, 134, 1, 0, 0, 0, 25, 137, 1, 0, 0, 0, 27, 140, 1, 0, 0, 0, 29, 145, 1, 0, 0, 0, 31, 151, 1, 0, 0, 0, 33, 162, 1, 0, 0, 0, 35, 170, 1, 0, 0, 0, 37, 179, 1, 0, 0, 0, 39, 188, 1, 0, 0, 0, 41, 195, 1, 0, 0, 0, 43, 202, 1, 0, 0, 0, 45, 204, 1, 0, 0, 0, 47, 207, 1, 0, 0, 0, 49, 212, 1, 0, 0, 0, 51, 218, 1, 0, 0, 0, 53, 223, 1, 0, 0, 0, 55, 225, 1, 0, 0, 0, 57, 227, 1, 0, 0, 0, 59, 229, 1, 0, 0, 0, 61, 231, 1, 0, 0, 0, 63, 233, 1, 0, 0, 0, 65, 235, 1, 0, 0, 0, 67, 237, 1, 0, 0, 0, 69, 239, 1, 0, 0, 0, 71, 241, 1, 0, 0, 0, 73, 244, 1, 0, 0, 0, 75, 246, 1, 0, 0, 0, 77, 251, 1, 0, 0, 0, 79, 254, 1, 0, 0, 0, 81, 266, 1, 0, 0, 0, 83, 277, 1, 0, 0, 0, 85, 282, 1, 0, 0, 0, 87, 289, 1, 0, 0, 0, 89, 321, 1, 0, 0, 0, 91, 323, 1, 0, 0, 0, 93, 328, 1, 0, 0, 0, 95, 333, 1, 0, 0, 0, 97, 339, 1, 0, 0, 0, 99, 341, 1, 0, 0, 0, 101, 343, 1, 0, 0, 0, 103, 346, 1, 0, 0, 0, 105, 350, 1, 0, 0, 0, 107, 108, 5, 64, 0, 0, 108, 2, 1, 0, 0, 0, 109, 110, 5, 46, 0, 0, 110, 111, 5, 46, 0, 0, 111, 4, 1, 0, 0, 0, 112, 113, 5, 36, 0, 0, 113, 6, 1, 0, 0, 0, 114, 115, 5, 46, 0, 0, 115, 8, 1, 0, 0, 0, 116, 117, 5, 42, 0, 0, 117, 10, 1, 0, 0, 0, 118, 119, 5, 38, 0, 0, 119, 120, 5, 38, 0, 0, 120, 12, 1, 0, 0, 0, 121, 122, 5, 61, 0, 0, 122, 123, 5, 61, 0, 0, 123, 14, 1, 0, 0, 0, 124, 125, 5, 62, 0, 0, 125, 126, 5, 61, 0, 0, 126, 16, 1, 0, 0, 0, 127, 128, 5, 62, 0, 0, 128, 18, 1, 0, 0, 0, 129, 130, 5, 60, 0, 0, 130, 131, 5, 61, 0, 0, 131, 20, 1, 0, 0, 0, 132, 133, 5, 60, 0, 0, 133, 22, 1, 0, 0, 0, 134, 135, 5, 33, 0, 0, 135, 136, 5, 61, 0, 0, 136, 24, 1, 0, 0, 0, 137, 138, 5, 61, 0, 0, 138, 139, 5, 126, 0, 0, 139, 26, 1, 0, 0, 0, 140, 141, 5, 32, 0, 0, 141, 142, 5, 105, 0, 0, 142, 143, 5, 110, 0, 0, 143, 144, 5, 32, 0, 0, 144, 28, 1, 0, 0, 0, 145, 146, 5, 32, 0, 0, 146, 147, 5, 110, 0, 0, 147, 148, 5, 105, 0, 0, 148, 149, 5, 110, 0, 0, 149, 150, 5, 32, 0, 0, 150, 30, 1, 0, 0, 0, 151, 152, 5, 32, 0, 0, 152, 153, 5, 115, 0, 0, 153, 154, 5, 117, 0, 0, 154, 155, 5, 98, 0, 0, 155, 156, 5, 115, 0, 0, 156, 157, 5, 101, 0, 0, 157, 158, 5, 116, 0, 0, 158, 159, 5, 111, 0, 0, 159, 160, 5, 102, 0, 0, 160, 161, 5, 32, 0, 0, 161, 32, 1, 0, 0, 0, 162, 163, 5, 32, 0, 0, 163, 164, 5, 97, 0, 0, 164, 165, 5, 110, 0, 0, 165, 166, 5, 121, 0, 0, 166, 167, 5, 111, 0, 0, 167, 168, 5, 102, 0, 0, 168, 169, 5, 32, 0, 0, 169, 34, 1, 0, 0, 0, 170, 171, 5, 32, 0, 0, 171, 172, 5, 110, 0, 0, 172, 173, 5, 111, 0, 0, 173, 174, 5, 110, 0, 0, 174, 175, 5, 101, 0, 0, 175, 176, 5, 111, 0, 0, 176, 177, 5, 102, 0, 0, 177, 178, 5, 32, 0, 0, 178, 36, 1, 0, 0, 0, 179, 180, 5, 32, 0, 0, 180, 181, 5, 115, 0, 0, 181, 182, 5, 105, 0, 0, 182, 183, 5, 122, 0, 0, 183, 184, 5, 101, 0, 0, 184, 185, 5, 111, 0, 0, 185, 186, 5, 102, 0, 0, 186, 187, 5, 32, 0, 0, 187, 38, 1, 0, 0, 0, 188, 189, 5, 32, 0, 0, 189, 190, 5, 115, 0, 0, 190, 191, 5, 105, 0, 0, 191, 192, 5, 122, 0, 0, 192, 193, 5, 101, 0, 0, 193, 194, 5, 32, 0, 0, 194, 40, 1, 0, 0, 0, 195, 196, 5, 32, 0, 0, 196, 197, 5, 101, 0, 0, 197, 198, 5, 109, 0, 0, 198, 199, 5, 112, 0, 0, 199, 200, 5, 116, 0, 0, 200, 201, 5, 121, 0, 0, 201, 42, 1, 0, 0, 0, 202, 203, 5, 33, 0, 0, 203, 44, 1, 0, 0, 0, 204, 205, 5, 124, 0, 0, 205, 206, 5, 124, 0, 0, 206, 46, 1, 0, 0, 0, 207, 208, 5, 116, 0, 0, 208, 209, 5, 114, 0, 0, 209, 210, 5, 117, 0, 0, 210, 211, 5, 101, 0, 0, 211, 48, 1, 0, 0, 0, 212, 213, 5, 102, 0, 0, 213, 214, 5, 97, 0, 0, 214, 215, 5, 108, 0, 0, 215, 216, 5, 115, 0, 0, 216, 217, 5, 101, 0, 0, 217, 50, 1, 0, 0, 0, 218, 219, 5, 110, 0, 0, 219, 220, 5, 117, 0, 0, 220, 221, 5, 108, 0, 0, 221, 222, 5, 108, 0, 0, 222, 52, 1, 0, 0, 0, 223, 224, 5, 123, 0, 0, 224, 54, 1, 0, 0, 0, 225, 226, 5, 125, 0, 0, 226, 56, 1, 0, 0, 0, 227, 228, 5, 91, 0, 0, 228, 58, 1, 0, 0, 0, 229, 230, 5, 93, 0, 0, 230, 60, 1, 0, 0, 0, 231, 232, 5, 58, 0, 0, 232, 62, 1, 0, 0, 0, 233, 234, 5, 44, 0, 0, 234, 64, 1, 0, 0, 0, 235, 236, 5, 40, 0, 0, 236, 66, 1, 0, 0, 0, 237, 238, 5, 41, 0, 0, 238, 68, 1, 0, 0, 0, 239, 240, 5, 63, 0, 0, 240, 70, 1, 0, 0, 0, 241, 242, 5, 45, 0, 0, 242, 243, 5, 32, 0, 0, 243, 72, 1, 0, 0, 0, 244, 245, 5, 43, 0, 0, 245, 74, 1, 0, 0, 0, 246, 247, 5, 47, 0, 0, 247, 76, 1, 0, 0, 0, 248, 250, 7, 0, 0, 0, 249, 248, 1, 0, 0, 0, 250, 253, 1, 0, 0, 0, 251, 249, 1, 0, 0, 0, 251, 252, 1, 0, 0, 0, 252, 78, 1, 0, 0, 0, 253, 251, 1, 0, 0, 0, 254, 258, 5, 47, 0, 0, 255, 257, 9, 0, 0, 0, 256, 255, 1, 0, 0, 0, 257, 260, 1, 0, 0, 0, 258, 259, 1, 0, 0, 0, 258, 256, 1, 0, 0, 0, 259, 261, 1, 0, 0, 0, 260, 258, 1, 0, 0, 0, 261, 262, 5, 47, 0, 0, 262, 80, 1, 0, 0, 0, 263, 265, 7, 1, 0, 0, 264, 263, 1, 0, 0, 0, 265, 268, 1, 0, 0, 0, 266, 264, 1, 0, 0, 0, 266, 267, 1, 0, 0, 0, 267, 269, 1, 0, 0, 0, 268, 266, 1, 0, 0, 0, 269, 273, 7, 2, 0, 0, 270, 272, 7, 3, 0, 0, 271, 270, 1, 0, 0, 0, 272, 275, 1, 0, 0, 0, 273, 271, 1, 0, 0, 0, 273, 274, 1, 0, 0, 0, 274, 82, 1, 0, 0, 0, 275, 273, 1, 0, 0, 0, 276, 278, 7, 4, 0, 0, 277, 276, 1, 0, 0, 0, 278, 279, 1, 0, 0, 0, 279, 277, 1, 0, 0, 0, 279, 280, 1, 0, 0, 0, 280, 84, 1, 0, 0, 0, 281, 283, 7, 5, 0, 0, 282, 281, 1, 0, 0, 0, 283, 284, 1, 0, 0, 0, 284, 282, 1, 0, 0, 0, 284, 285, 1, 0, 0, 0, 285, 286, 1, 0, 0, 0, 286, 287, 6, 42, 0, 0, 287, 86, 1, 0, 0, 0, 288, 290, 5, 45, 0, 0, 289, 288, 1, 0, 0, 0, 289, 290, 1, 0, 0, 0, 290, 291, 1, 0, 0, 0, 291, 298, 3, 103, 51, 0, 292, 294, 5, 46, 0, 0, 293, 295, 7, 6, 0, 0, 294, 293, 1, 0, 0, 0, 295, 296, 1, 0, 0, 0, 296, 294, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, 299, 1, 0, 0, 0, 298, 292, 1, 0, 0, 0, 298, 299, 1, 0, 0, 0, 299, 301, 1, 0, 0, 0, 300, 302, 3, 105, 52, 0, 301, 300, 1, 0, 0, 0, 301, 302, 1, 0, 0, 0, 302, 88, 1, 0, 0, 0, 303, 308, 5, 34, 0, 0, 304, 307, 3, 93, 46, 0, 305, 307, 3, 101, 50, 0, 306, 304, 1, 0, 0, 0, 306, 305, 1, 0, 0, 0, 307, 310, 1, 0, 0, 0, 308, 306, 1, 0, 0, 0, 308, 309, 1, 0, 0, 0, 309, 311, 1, 0, 0, 0, 310, 308, 1, 0, 0, 0, 311, 322, 5, 34, 0, 0, 312, 317, 5, 39, 0, 0, 313, 316, 3, 91, 45, 0, 314, 316, 3, 99, 49, 0, 315, 313, 1, 0, 0, 0, 315, 314, 1, 0, 0, 0, 316, 319, 1, 0, 0, 0, 317, 315, 1, 0, 0, 0, 317, 318, 1, 0, 0, 0, 318, 320, 1, 0, 0, 0, 319, 317, 1, 0, 0, 0, 320, 322, 5, 39, 0, 0, 321, 303, 1, 0, 0, 0, 321, 312, 1, 0, 0, 0, 322, 90, 1, 0, 0, 0, 323, 326, 5, 92, 0, 0, 324, 327, 7, 7, 0, 0, 325, 327, 3, 95, 47, 0, 326, 324, 1, 0, 0, 0, 326, 325, 1, 0, 0, 0, 327, 92, 1, 0, 0, 0, 328, 331, 5, 92, 0, 0, 329, 332, 7, 8, 0, 0, 330, 332, 3, 95, 47, 0, 331, 329, 1, 0, 0, 0, 331, 330, 1, 0, 0, 0, 332, 94, 1, 0, 0, 0, 333, 334, 5, 117, 0, 0, 334, 335, 3, 97, 48, 0, 335, 336, 3, 97, 48, 0, 336, 337, 3, 97, 48, 0, 337, 338, 3, 97, 48, 0, 338, 96, 1, 0, 0, 0, 339, 340, 7, 9, 0, 0, 340, 98, 1, 0, 0, 0, 341, 342, 8, 10, 0, 0, 342, 100, 1, 0, 0, 0, 343, 344, 8, 11, 0, 0, 344, 102, 1, 0, 0, 0, 345, 347, 7, 6, 0, 0, 346, 345, 1, 0, 0, 0, 347, 348, 1, 0, 0, 0, 348, 346, 1, 0, 0, 0, 348, 349, 1, 0, 0, 0, 349, 104, 1, 0, 0, 0, 350, 352, 7, 12, 0, 0, 351, 353, 7, 13, 0, 0, 352, 351, 1, 0, 0, 0, 352, 353, 1, 0, 0, 0, 353, 354, 1, 0, 0, 0, 354, 355, 3, 103, 51, 0, 355, 106, 1, 0, 0, 0, 20, 0, 251, 258, 266, 273, 279, 284, 289, 296, 298, 301, 306, 308, 315, 317, 321, 326, 331, 348, 352, 1, 6, 0, 0]
--------------------------------------------------------------------------------
/src/parser/generated/JSONPathLexer.js:
--------------------------------------------------------------------------------
1 | // Generated from ./src/parser/generated/JSONPath.g4 by ANTLR 4.13.1
2 | // jshint ignore: start
3 | import antlr4 from 'antlr4';
4 |
5 |
6 | const serializedATN = [4,0,45,356,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,
7 | 4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,
8 | 12,2,13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,19,
9 | 2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,26,7,26,2,
10 | 27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2,31,7,31,2,32,7,32,2,33,7,33,2,34,
11 | 7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38,7,38,2,39,7,39,2,40,7,40,2,41,7,
12 | 41,2,42,7,42,2,43,7,43,2,44,7,44,2,45,7,45,2,46,7,46,2,47,7,47,2,48,7,48,
13 | 2,49,7,49,2,50,7,50,2,51,7,51,2,52,7,52,1,0,1,0,1,1,1,1,1,1,1,2,1,2,1,3,
14 | 1,3,1,4,1,4,1,5,1,5,1,5,1,6,1,6,1,6,1,7,1,7,1,7,1,8,1,8,1,9,1,9,1,9,1,10,
15 | 1,10,1,11,1,11,1,11,1,12,1,12,1,12,1,13,1,13,1,13,1,13,1,13,1,14,1,14,1,
16 | 14,1,14,1,14,1,14,1,15,1,15,1,15,1,15,1,15,1,15,1,15,1,15,1,15,1,15,1,15,
17 | 1,16,1,16,1,16,1,16,1,16,1,16,1,16,1,16,1,17,1,17,1,17,1,17,1,17,1,17,1,
18 | 17,1,17,1,17,1,18,1,18,1,18,1,18,1,18,1,18,1,18,1,18,1,18,1,19,1,19,1,19,
19 | 1,19,1,19,1,19,1,19,1,20,1,20,1,20,1,20,1,20,1,20,1,20,1,21,1,21,1,22,1,
20 | 22,1,22,1,23,1,23,1,23,1,23,1,23,1,24,1,24,1,24,1,24,1,24,1,24,1,25,1,25,
21 | 1,25,1,25,1,25,1,26,1,26,1,27,1,27,1,28,1,28,1,29,1,29,1,30,1,30,1,31,1,
22 | 31,1,32,1,32,1,33,1,33,1,34,1,34,1,35,1,35,1,35,1,36,1,36,1,37,1,37,1,38,
23 | 5,38,250,8,38,10,38,12,38,253,9,38,1,39,1,39,5,39,257,8,39,10,39,12,39,260,
24 | 9,39,1,39,1,39,1,40,5,40,265,8,40,10,40,12,40,268,9,40,1,40,1,40,5,40,272,
25 | 8,40,10,40,12,40,275,9,40,1,41,4,41,278,8,41,11,41,12,41,279,1,42,4,42,283,
26 | 8,42,11,42,12,42,284,1,42,1,42,1,43,3,43,290,8,43,1,43,1,43,1,43,4,43,295,
27 | 8,43,11,43,12,43,296,3,43,299,8,43,1,43,3,43,302,8,43,1,44,1,44,1,44,5,44,
28 | 307,8,44,10,44,12,44,310,9,44,1,44,1,44,1,44,1,44,5,44,316,8,44,10,44,12,
29 | 44,319,9,44,1,44,3,44,322,8,44,1,45,1,45,1,45,3,45,327,8,45,1,46,1,46,1,
30 | 46,3,46,332,8,46,1,47,1,47,1,47,1,47,1,47,1,47,1,48,1,48,1,49,1,49,1,50,
31 | 1,50,1,51,4,51,347,8,51,11,51,12,51,348,1,52,1,52,3,52,353,8,52,1,52,1,52,
32 | 1,258,0,53,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,
33 | 13,27,14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,22,45,23,47,24,49,
34 | 25,51,26,53,27,55,28,57,29,59,30,61,31,63,32,65,33,67,34,69,35,71,36,73,
35 | 37,75,38,77,39,79,40,81,41,83,42,85,43,87,44,89,45,91,0,93,0,95,0,97,0,99,
36 | 0,101,0,103,0,105,0,1,0,14,6,0,103,103,105,105,109,109,115,115,117,117,121,
37 | 121,4,0,45,45,65,90,95,95,97,122,3,0,65,90,95,95,97,122,4,0,48,57,65,90,
38 | 95,95,97,122,2,0,95,95,128,65535,3,0,9,10,13,13,32,32,1,0,48,57,8,0,39,39,
39 | 47,47,92,92,98,98,102,102,110,110,114,114,116,116,8,0,34,34,47,47,92,92,
40 | 98,98,102,102,110,110,114,114,116,116,3,0,48,57,65,70,97,102,3,0,0,31,39,
41 | 39,92,92,3,0,0,31,34,34,92,92,2,0,69,69,101,101,2,0,43,43,45,45,366,0,1,
42 | 1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,
43 | 1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1,0,0,0,
44 | 0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1,0,0,0,0,35,1,
45 | 0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,0,0,45,1,0,0,0,0,
46 | 47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,1,0,0,0,0,55,1,0,0,0,0,57,1,0,
47 | 0,0,0,59,1,0,0,0,0,61,1,0,0,0,0,63,1,0,0,0,0,65,1,0,0,0,0,67,1,0,0,0,0,69,
48 | 1,0,0,0,0,71,1,0,0,0,0,73,1,0,0,0,0,75,1,0,0,0,0,77,1,0,0,0,0,79,1,0,0,0,
49 | 0,81,1,0,0,0,0,83,1,0,0,0,0,85,1,0,0,0,0,87,1,0,0,0,0,89,1,0,0,0,1,107,1,
50 | 0,0,0,3,109,1,0,0,0,5,112,1,0,0,0,7,114,1,0,0,0,9,116,1,0,0,0,11,118,1,0,
51 | 0,0,13,121,1,0,0,0,15,124,1,0,0,0,17,127,1,0,0,0,19,129,1,0,0,0,21,132,1,
52 | 0,0,0,23,134,1,0,0,0,25,137,1,0,0,0,27,140,1,0,0,0,29,145,1,0,0,0,31,151,
53 | 1,0,0,0,33,162,1,0,0,0,35,170,1,0,0,0,37,179,1,0,0,0,39,188,1,0,0,0,41,195,
54 | 1,0,0,0,43,202,1,0,0,0,45,204,1,0,0,0,47,207,1,0,0,0,49,212,1,0,0,0,51,218,
55 | 1,0,0,0,53,223,1,0,0,0,55,225,1,0,0,0,57,227,1,0,0,0,59,229,1,0,0,0,61,231,
56 | 1,0,0,0,63,233,1,0,0,0,65,235,1,0,0,0,67,237,1,0,0,0,69,239,1,0,0,0,71,241,
57 | 1,0,0,0,73,244,1,0,0,0,75,246,1,0,0,0,77,251,1,0,0,0,79,254,1,0,0,0,81,266,
58 | 1,0,0,0,83,277,1,0,0,0,85,282,1,0,0,0,87,289,1,0,0,0,89,321,1,0,0,0,91,323,
59 | 1,0,0,0,93,328,1,0,0,0,95,333,1,0,0,0,97,339,1,0,0,0,99,341,1,0,0,0,101,
60 | 343,1,0,0,0,103,346,1,0,0,0,105,350,1,0,0,0,107,108,5,64,0,0,108,2,1,0,0,
61 | 0,109,110,5,46,0,0,110,111,5,46,0,0,111,4,1,0,0,0,112,113,5,36,0,0,113,6,
62 | 1,0,0,0,114,115,5,46,0,0,115,8,1,0,0,0,116,117,5,42,0,0,117,10,1,0,0,0,118,
63 | 119,5,38,0,0,119,120,5,38,0,0,120,12,1,0,0,0,121,122,5,61,0,0,122,123,5,
64 | 61,0,0,123,14,1,0,0,0,124,125,5,62,0,0,125,126,5,61,0,0,126,16,1,0,0,0,127,
65 | 128,5,62,0,0,128,18,1,0,0,0,129,130,5,60,0,0,130,131,5,61,0,0,131,20,1,0,
66 | 0,0,132,133,5,60,0,0,133,22,1,0,0,0,134,135,5,33,0,0,135,136,5,61,0,0,136,
67 | 24,1,0,0,0,137,138,5,61,0,0,138,139,5,126,0,0,139,26,1,0,0,0,140,141,5,32,
68 | 0,0,141,142,5,105,0,0,142,143,5,110,0,0,143,144,5,32,0,0,144,28,1,0,0,0,
69 | 145,146,5,32,0,0,146,147,5,110,0,0,147,148,5,105,0,0,148,149,5,110,0,0,149,
70 | 150,5,32,0,0,150,30,1,0,0,0,151,152,5,32,0,0,152,153,5,115,0,0,153,154,5,
71 | 117,0,0,154,155,5,98,0,0,155,156,5,115,0,0,156,157,5,101,0,0,157,158,5,116,
72 | 0,0,158,159,5,111,0,0,159,160,5,102,0,0,160,161,5,32,0,0,161,32,1,0,0,0,
73 | 162,163,5,32,0,0,163,164,5,97,0,0,164,165,5,110,0,0,165,166,5,121,0,0,166,
74 | 167,5,111,0,0,167,168,5,102,0,0,168,169,5,32,0,0,169,34,1,0,0,0,170,171,
75 | 5,32,0,0,171,172,5,110,0,0,172,173,5,111,0,0,173,174,5,110,0,0,174,175,5,
76 | 101,0,0,175,176,5,111,0,0,176,177,5,102,0,0,177,178,5,32,0,0,178,36,1,0,
77 | 0,0,179,180,5,32,0,0,180,181,5,115,0,0,181,182,5,105,0,0,182,183,5,122,0,
78 | 0,183,184,5,101,0,0,184,185,5,111,0,0,185,186,5,102,0,0,186,187,5,32,0,0,
79 | 187,38,1,0,0,0,188,189,5,32,0,0,189,190,5,115,0,0,190,191,5,105,0,0,191,
80 | 192,5,122,0,0,192,193,5,101,0,0,193,194,5,32,0,0,194,40,1,0,0,0,195,196,
81 | 5,32,0,0,196,197,5,101,0,0,197,198,5,109,0,0,198,199,5,112,0,0,199,200,5,
82 | 116,0,0,200,201,5,121,0,0,201,42,1,0,0,0,202,203,5,33,0,0,203,44,1,0,0,0,
83 | 204,205,5,124,0,0,205,206,5,124,0,0,206,46,1,0,0,0,207,208,5,116,0,0,208,
84 | 209,5,114,0,0,209,210,5,117,0,0,210,211,5,101,0,0,211,48,1,0,0,0,212,213,
85 | 5,102,0,0,213,214,5,97,0,0,214,215,5,108,0,0,215,216,5,115,0,0,216,217,5,
86 | 101,0,0,217,50,1,0,0,0,218,219,5,110,0,0,219,220,5,117,0,0,220,221,5,108,
87 | 0,0,221,222,5,108,0,0,222,52,1,0,0,0,223,224,5,123,0,0,224,54,1,0,0,0,225,
88 | 226,5,125,0,0,226,56,1,0,0,0,227,228,5,91,0,0,228,58,1,0,0,0,229,230,5,93,
89 | 0,0,230,60,1,0,0,0,231,232,5,58,0,0,232,62,1,0,0,0,233,234,5,44,0,0,234,
90 | 64,1,0,0,0,235,236,5,40,0,0,236,66,1,0,0,0,237,238,5,41,0,0,238,68,1,0,0,
91 | 0,239,240,5,63,0,0,240,70,1,0,0,0,241,242,5,45,0,0,242,243,5,32,0,0,243,
92 | 72,1,0,0,0,244,245,5,43,0,0,245,74,1,0,0,0,246,247,5,47,0,0,247,76,1,0,0,
93 | 0,248,250,7,0,0,0,249,248,1,0,0,0,250,253,1,0,0,0,251,249,1,0,0,0,251,252,
94 | 1,0,0,0,252,78,1,0,0,0,253,251,1,0,0,0,254,258,5,47,0,0,255,257,9,0,0,0,
95 | 256,255,1,0,0,0,257,260,1,0,0,0,258,259,1,0,0,0,258,256,1,0,0,0,259,261,
96 | 1,0,0,0,260,258,1,0,0,0,261,262,5,47,0,0,262,80,1,0,0,0,263,265,7,1,0,0,
97 | 264,263,1,0,0,0,265,268,1,0,0,0,266,264,1,0,0,0,266,267,1,0,0,0,267,269,
98 | 1,0,0,0,268,266,1,0,0,0,269,273,7,2,0,0,270,272,7,3,0,0,271,270,1,0,0,0,
99 | 272,275,1,0,0,0,273,271,1,0,0,0,273,274,1,0,0,0,274,82,1,0,0,0,275,273,1,
100 | 0,0,0,276,278,7,4,0,0,277,276,1,0,0,0,278,279,1,0,0,0,279,277,1,0,0,0,279,
101 | 280,1,0,0,0,280,84,1,0,0,0,281,283,7,5,0,0,282,281,1,0,0,0,283,284,1,0,0,
102 | 0,284,282,1,0,0,0,284,285,1,0,0,0,285,286,1,0,0,0,286,287,6,42,0,0,287,86,
103 | 1,0,0,0,288,290,5,45,0,0,289,288,1,0,0,0,289,290,1,0,0,0,290,291,1,0,0,0,
104 | 291,298,3,103,51,0,292,294,5,46,0,0,293,295,7,6,0,0,294,293,1,0,0,0,295,
105 | 296,1,0,0,0,296,294,1,0,0,0,296,297,1,0,0,0,297,299,1,0,0,0,298,292,1,0,
106 | 0,0,298,299,1,0,0,0,299,301,1,0,0,0,300,302,3,105,52,0,301,300,1,0,0,0,301,
107 | 302,1,0,0,0,302,88,1,0,0,0,303,308,5,34,0,0,304,307,3,93,46,0,305,307,3,
108 | 101,50,0,306,304,1,0,0,0,306,305,1,0,0,0,307,310,1,0,0,0,308,306,1,0,0,0,
109 | 308,309,1,0,0,0,309,311,1,0,0,0,310,308,1,0,0,0,311,322,5,34,0,0,312,317,
110 | 5,39,0,0,313,316,3,91,45,0,314,316,3,99,49,0,315,313,1,0,0,0,315,314,1,0,
111 | 0,0,316,319,1,0,0,0,317,315,1,0,0,0,317,318,1,0,0,0,318,320,1,0,0,0,319,
112 | 317,1,0,0,0,320,322,5,39,0,0,321,303,1,0,0,0,321,312,1,0,0,0,322,90,1,0,
113 | 0,0,323,326,5,92,0,0,324,327,7,7,0,0,325,327,3,95,47,0,326,324,1,0,0,0,326,
114 | 325,1,0,0,0,327,92,1,0,0,0,328,331,5,92,0,0,329,332,7,8,0,0,330,332,3,95,
115 | 47,0,331,329,1,0,0,0,331,330,1,0,0,0,332,94,1,0,0,0,333,334,5,117,0,0,334,
116 | 335,3,97,48,0,335,336,3,97,48,0,336,337,3,97,48,0,337,338,3,97,48,0,338,
117 | 96,1,0,0,0,339,340,7,9,0,0,340,98,1,0,0,0,341,342,8,10,0,0,342,100,1,0,0,
118 | 0,343,344,8,11,0,0,344,102,1,0,0,0,345,347,7,6,0,0,346,345,1,0,0,0,347,348,
119 | 1,0,0,0,348,346,1,0,0,0,348,349,1,0,0,0,349,104,1,0,0,0,350,352,7,12,0,0,
120 | 351,353,7,13,0,0,352,351,1,0,0,0,352,353,1,0,0,0,353,354,1,0,0,0,354,355,
121 | 3,103,51,0,355,106,1,0,0,0,20,0,251,258,266,273,279,284,289,296,298,301,
122 | 306,308,315,317,321,326,331,348,352,1,6,0,0];
123 |
124 |
125 | const atn = new antlr4.atn.ATNDeserializer().deserialize(serializedATN);
126 |
127 | const decisionsToDFA = atn.decisionToState.map( (ds, index) => new antlr4.dfa.DFA(ds, index) );
128 |
129 | export default class JSONPathLexer extends antlr4.Lexer {
130 |
131 | static grammarFileName = "JSONPath.g4";
132 | static channelNames = [ "DEFAULT_TOKEN_CHANNEL", "HIDDEN" ];
133 | static modeNames = [ "DEFAULT_MODE" ];
134 | static literalNames = [ null, "'@'", "'..'", "'$'", "'.'", "'*'", "'&&'",
135 | "'=='", "'>='", "'>'", "'<='", "'<'", "'!='", "'=~'",
136 | "' in '", "' nin '", "' subsetof '", "' anyof '",
137 | "' noneof '", "' sizeof '", "' size '", "' empty'",
138 | "'!'", "'||'", "'true'", "'false'", "'null'", "'{'",
139 | "'}'", "'['", "']'", "':'", "','", "'('", "')'",
140 | "'?'", "'- '", "'+'", "'/'" ];
141 | static symbolicNames = [ null, "CURRENT_VALUE", "DOTDOT", "ROOT_VALUE",
142 | "DOT", "STAR", "AND", "EQ", "GE", "GT", "LE",
143 | "LT", "NE", "REG", "IN", "NIN", "SUB", "ANY",
144 | "NON", "SIZO", "SIZ", "EMPT", "NOT", "OR", "TRUE",
145 | "FALSE", "NULL", "BRACE_LEFT", "BRACE_RIGHT",
146 | "BRACKET_LEFT", "BRACKET_RIGHT", "COLON", "COMMA",
147 | "PAREN_LEFT", "PAREN_RIGHT", "QUESTION", "MINUS_SP",
148 | "PLUS", "DIV", "REGEX_OPT", "REGEX_EXPR", "KEY",
149 | "SPECIAL_KEY", "WS", "NUMBER", "STRING" ];
150 | static ruleNames = [ "CURRENT_VALUE", "DOTDOT", "ROOT_VALUE", "DOT", "STAR",
151 | "AND", "EQ", "GE", "GT", "LE", "LT", "NE", "REG",
152 | "IN", "NIN", "SUB", "ANY", "NON", "SIZO", "SIZ", "EMPT",
153 | "NOT", "OR", "TRUE", "FALSE", "NULL", "BRACE_LEFT",
154 | "BRACE_RIGHT", "BRACKET_LEFT", "BRACKET_RIGHT", "COLON",
155 | "COMMA", "PAREN_LEFT", "PAREN_RIGHT", "QUESTION",
156 | "MINUS_SP", "PLUS", "DIV", "REGEX_OPT", "REGEX_EXPR",
157 | "KEY", "SPECIAL_KEY", "WS", "NUMBER", "STRING", "ESC_SINGLE",
158 | "ESC_DOUBLE", "UNICODE", "HEX", "SAFECODEPOINT_SINGLE",
159 | "SAFECODEPOINT_DOUBLE", "INT", "EXP" ];
160 |
161 | constructor(input) {
162 | super(input)
163 | this._interp = new antlr4.atn.LexerATNSimulator(this, atn, decisionsToDFA, new antlr4.atn.PredictionContextCache());
164 | }
165 | }
166 |
167 | JSONPathLexer.EOF = antlr4.Token.EOF;
168 | JSONPathLexer.CURRENT_VALUE = 1;
169 | JSONPathLexer.DOTDOT = 2;
170 | JSONPathLexer.ROOT_VALUE = 3;
171 | JSONPathLexer.DOT = 4;
172 | JSONPathLexer.STAR = 5;
173 | JSONPathLexer.AND = 6;
174 | JSONPathLexer.EQ = 7;
175 | JSONPathLexer.GE = 8;
176 | JSONPathLexer.GT = 9;
177 | JSONPathLexer.LE = 10;
178 | JSONPathLexer.LT = 11;
179 | JSONPathLexer.NE = 12;
180 | JSONPathLexer.REG = 13;
181 | JSONPathLexer.IN = 14;
182 | JSONPathLexer.NIN = 15;
183 | JSONPathLexer.SUB = 16;
184 | JSONPathLexer.ANY = 17;
185 | JSONPathLexer.NON = 18;
186 | JSONPathLexer.SIZO = 19;
187 | JSONPathLexer.SIZ = 20;
188 | JSONPathLexer.EMPT = 21;
189 | JSONPathLexer.NOT = 22;
190 | JSONPathLexer.OR = 23;
191 | JSONPathLexer.TRUE = 24;
192 | JSONPathLexer.FALSE = 25;
193 | JSONPathLexer.NULL = 26;
194 | JSONPathLexer.BRACE_LEFT = 27;
195 | JSONPathLexer.BRACE_RIGHT = 28;
196 | JSONPathLexer.BRACKET_LEFT = 29;
197 | JSONPathLexer.BRACKET_RIGHT = 30;
198 | JSONPathLexer.COLON = 31;
199 | JSONPathLexer.COMMA = 32;
200 | JSONPathLexer.PAREN_LEFT = 33;
201 | JSONPathLexer.PAREN_RIGHT = 34;
202 | JSONPathLexer.QUESTION = 35;
203 | JSONPathLexer.MINUS_SP = 36;
204 | JSONPathLexer.PLUS = 37;
205 | JSONPathLexer.DIV = 38;
206 | JSONPathLexer.REGEX_OPT = 39;
207 | JSONPathLexer.REGEX_EXPR = 40;
208 | JSONPathLexer.KEY = 41;
209 | JSONPathLexer.SPECIAL_KEY = 42;
210 | JSONPathLexer.WS = 43;
211 | JSONPathLexer.NUMBER = 44;
212 | JSONPathLexer.STRING = 45;
213 |
214 |
215 |
216 |
--------------------------------------------------------------------------------
/src/parser/generated/JSONPathLexer.tokens:
--------------------------------------------------------------------------------
1 | CURRENT_VALUE=1
2 | DOTDOT=2
3 | ROOT_VALUE=3
4 | DOT=4
5 | STAR=5
6 | AND=6
7 | EQ=7
8 | GE=8
9 | GT=9
10 | LE=10
11 | LT=11
12 | NE=12
13 | REG=13
14 | IN=14
15 | NIN=15
16 | SUB=16
17 | ANY=17
18 | NON=18
19 | SIZO=19
20 | SIZ=20
21 | EMPT=21
22 | NOT=22
23 | OR=23
24 | TRUE=24
25 | FALSE=25
26 | NULL=26
27 | BRACE_LEFT=27
28 | BRACE_RIGHT=28
29 | BRACKET_LEFT=29
30 | BRACKET_RIGHT=30
31 | COLON=31
32 | COMMA=32
33 | PAREN_LEFT=33
34 | PAREN_RIGHT=34
35 | QUESTION=35
36 | MINUS_SP=36
37 | PLUS=37
38 | DIV=38
39 | REGEX_OPT=39
40 | REGEX_EXPR=40
41 | KEY=41
42 | SPECIAL_KEY=42
43 | WS=43
44 | NUMBER=44
45 | STRING=45
46 | '@'=1
47 | '..'=2
48 | '$'=3
49 | '.'=4
50 | '*'=5
51 | '&&'=6
52 | '=='=7
53 | '>='=8
54 | '>'=9
55 | '<='=10
56 | '<'=11
57 | '!='=12
58 | '=~'=13
59 | ' in '=14
60 | ' nin '=15
61 | ' subsetof '=16
62 | ' anyof '=17
63 | ' noneof '=18
64 | ' sizeof '=19
65 | ' size '=20
66 | ' empty'=21
67 | '!'=22
68 | '||'=23
69 | 'true'=24
70 | 'false'=25
71 | 'null'=26
72 | '{'=27
73 | '}'=28
74 | '['=29
75 | ']'=30
76 | ':'=31
77 | ','=32
78 | '('=33
79 | ')'=34
80 | '?'=35
81 | '- '=36
82 | '+'=37
83 | '/'=38
84 |
--------------------------------------------------------------------------------
/src/parser/generated/JSONPathListener.js:
--------------------------------------------------------------------------------
1 | // Generated from ./src/parser/generated/JSONPath.g4 by ANTLR 4.13.1
2 | // jshint ignore: start
3 | import antlr4 from 'antlr4';
4 |
5 | // This class defines a complete listener for a parse tree produced by JSONPathParser.
6 | export default class JSONPathListener extends antlr4.tree.ParseTreeListener {
7 |
8 | // Enter a parse tree produced by JSONPathParser#jsonpath.
9 | enterJsonpath(ctx) {
10 | }
11 |
12 | // Exit a parse tree produced by JSONPathParser#jsonpath.
13 | exitJsonpath(ctx) {
14 | }
15 |
16 |
17 | // Enter a parse tree produced by JSONPathParser#filterarg.
18 | enterFilterarg(ctx) {
19 | }
20 |
21 | // Exit a parse tree produced by JSONPathParser#filterarg.
22 | exitFilterarg(ctx) {
23 | }
24 |
25 |
26 | // Enter a parse tree produced by JSONPathParser#subscript.
27 | enterSubscript(ctx) {
28 | }
29 |
30 | // Exit a parse tree produced by JSONPathParser#subscript.
31 | exitSubscript(ctx) {
32 | }
33 |
34 |
35 | // Enter a parse tree produced by JSONPathParser#dotdotContent.
36 | enterDotdotContent(ctx) {
37 | }
38 |
39 | // Exit a parse tree produced by JSONPathParser#dotdotContent.
40 | exitDotdotContent(ctx) {
41 | }
42 |
43 |
44 | // Enter a parse tree produced by JSONPathParser#dotContent.
45 | enterDotContent(ctx) {
46 | }
47 |
48 | // Exit a parse tree produced by JSONPathParser#dotContent.
49 | exitDotContent(ctx) {
50 | }
51 |
52 |
53 | // Enter a parse tree produced by JSONPathParser#bracket.
54 | enterBracket(ctx) {
55 | }
56 |
57 | // Exit a parse tree produced by JSONPathParser#bracket.
58 | exitBracket(ctx) {
59 | }
60 |
61 |
62 | // Enter a parse tree produced by JSONPathParser#bracketContent.
63 | enterBracketContent(ctx) {
64 | }
65 |
66 | // Exit a parse tree produced by JSONPathParser#bracketContent.
67 | exitBracketContent(ctx) {
68 | }
69 |
70 |
71 | // Enter a parse tree produced by JSONPathParser#filterExpression.
72 | enterFilterExpression(ctx) {
73 | }
74 |
75 | // Exit a parse tree produced by JSONPathParser#filterExpression.
76 | exitFilterExpression(ctx) {
77 | }
78 |
79 |
80 | // Enter a parse tree produced by JSONPathParser#indexes.
81 | enterIndexes(ctx) {
82 | }
83 |
84 | // Exit a parse tree produced by JSONPathParser#indexes.
85 | exitIndexes(ctx) {
86 | }
87 |
88 |
89 | // Enter a parse tree produced by JSONPathParser#unions.
90 | enterUnions(ctx) {
91 | }
92 |
93 | // Exit a parse tree produced by JSONPathParser#unions.
94 | exitUnions(ctx) {
95 | }
96 |
97 |
98 | // Enter a parse tree produced by JSONPathParser#slices.
99 | enterSlices(ctx) {
100 | }
101 |
102 | // Exit a parse tree produced by JSONPathParser#slices.
103 | exitSlices(ctx) {
104 | }
105 |
106 |
107 | // Enter a parse tree produced by JSONPathParser#regex.
108 | enterRegex(ctx) {
109 | }
110 |
111 | // Exit a parse tree produced by JSONPathParser#regex.
112 | exitRegex(ctx) {
113 | }
114 |
115 |
116 | // Enter a parse tree produced by JSONPathParser#expression.
117 | enterExpression(ctx) {
118 | }
119 |
120 | // Exit a parse tree produced by JSONPathParser#expression.
121 | exitExpression(ctx) {
122 | }
123 |
124 |
125 | // Enter a parse tree produced by JSONPathParser#filterpath.
126 | enterFilterpath(ctx) {
127 | }
128 |
129 | // Exit a parse tree produced by JSONPathParser#filterpath.
130 | exitFilterpath(ctx) {
131 | }
132 |
133 |
134 | // Enter a parse tree produced by JSONPathParser#identifier.
135 | enterIdentifier(ctx) {
136 | }
137 |
138 | // Exit a parse tree produced by JSONPathParser#identifier.
139 | exitIdentifier(ctx) {
140 | }
141 |
142 |
143 | // Enter a parse tree produced by JSONPathParser#obj.
144 | enterObj(ctx) {
145 | }
146 |
147 | // Exit a parse tree produced by JSONPathParser#obj.
148 | exitObj(ctx) {
149 | }
150 |
151 |
152 | // Enter a parse tree produced by JSONPathParser#pair.
153 | enterPair(ctx) {
154 | }
155 |
156 | // Exit a parse tree produced by JSONPathParser#pair.
157 | exitPair(ctx) {
158 | }
159 |
160 |
161 | // Enter a parse tree produced by JSONPathParser#array.
162 | enterArray(ctx) {
163 | }
164 |
165 | // Exit a parse tree produced by JSONPathParser#array.
166 | exitArray(ctx) {
167 | }
168 |
169 |
170 | // Enter a parse tree produced by JSONPathParser#value.
171 | enterValue(ctx) {
172 | }
173 |
174 | // Exit a parse tree produced by JSONPathParser#value.
175 | exitValue(ctx) {
176 | }
177 |
178 |
179 |
180 | }
--------------------------------------------------------------------------------
/src/parser/generated/JSONPathParser.js:
--------------------------------------------------------------------------------
1 | // Generated from ./src/parser/generated/JSONPath.g4 by ANTLR 4.13.1
2 | // jshint ignore: start
3 | import antlr4 from 'antlr4';
4 | import JSONPathListener from './JSONPathListener.js';
5 | const serializedATN = [4,1,45,236,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,
6 | 4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,
7 | 2,13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,1,0,1,0,3,0,
8 | 41,8,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,52,8,1,1,1,1,1,1,1,1,1,1,
9 | 1,3,1,59,8,1,1,1,5,1,62,8,1,10,1,12,1,65,9,1,1,2,1,2,1,2,3,2,70,8,2,1,2,
10 | 1,2,1,2,3,2,75,8,2,1,2,1,2,3,2,79,8,2,3,2,81,8,2,1,3,1,3,1,3,3,3,86,8,3,
11 | 1,4,1,4,1,4,3,4,91,8,4,1,5,1,5,1,5,1,5,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6,3,
12 | 6,105,8,6,1,7,1,7,1,7,1,7,1,7,1,8,1,8,1,8,4,8,115,8,8,11,8,12,8,116,1,9,
13 | 1,9,1,9,4,9,122,8,9,11,9,12,9,123,1,9,1,9,1,9,4,9,129,8,9,11,9,12,9,130,
14 | 3,9,133,8,9,1,10,3,10,136,8,10,1,10,1,10,3,10,140,8,10,1,10,1,10,3,10,144,
15 | 8,10,3,10,146,8,10,1,11,1,11,3,11,150,8,11,1,12,1,12,1,12,1,12,1,12,1,12,
16 | 1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,
17 | 12,1,12,1,12,1,12,1,12,3,12,177,8,12,1,12,1,12,1,12,5,12,182,8,12,10,12,
18 | 12,12,185,9,12,1,13,1,13,3,13,189,8,13,1,14,1,14,1,15,1,15,1,15,1,15,5,15,
19 | 197,8,15,10,15,12,15,200,9,15,1,15,1,15,1,15,1,15,3,15,206,8,15,1,16,1,16,
20 | 1,16,1,16,1,17,1,17,1,17,1,17,5,17,216,8,17,10,17,12,17,219,9,17,1,17,1,
21 | 17,1,17,1,17,3,17,225,8,17,1,18,1,18,1,18,1,18,1,18,1,18,1,18,3,18,234,8,
22 | 18,1,18,0,2,2,24,19,0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,
23 | 0,6,2,0,5,5,38,38,1,0,36,37,2,0,7,12,14,20,2,0,6,6,23,23,2,0,1,1,3,3,2,0,
24 | 24,26,41,42,267,0,38,1,0,0,0,2,51,1,0,0,0,4,80,1,0,0,0,6,85,1,0,0,0,8,90,
25 | 1,0,0,0,10,92,1,0,0,0,12,104,1,0,0,0,14,106,1,0,0,0,16,111,1,0,0,0,18,132,
26 | 1,0,0,0,20,135,1,0,0,0,22,147,1,0,0,0,24,176,1,0,0,0,26,186,1,0,0,0,28,190,
27 | 1,0,0,0,30,205,1,0,0,0,32,207,1,0,0,0,34,224,1,0,0,0,36,233,1,0,0,0,38,40,
28 | 5,3,0,0,39,41,3,4,2,0,40,39,1,0,0,0,40,41,1,0,0,0,41,42,1,0,0,0,42,43,5,
29 | 0,0,1,43,1,1,0,0,0,44,45,6,1,-1,0,45,46,5,33,0,0,46,47,3,2,1,0,47,48,5,34,
30 | 0,0,48,52,1,0,0,0,49,52,3,36,18,0,50,52,3,26,13,0,51,44,1,0,0,0,51,49,1,
31 | 0,0,0,51,50,1,0,0,0,52,63,1,0,0,0,53,54,10,4,0,0,54,55,7,0,0,0,55,62,3,2,
32 | 1,5,56,58,10,3,0,0,57,59,7,1,0,0,58,57,1,0,0,0,58,59,1,0,0,0,59,60,1,0,0,
33 | 0,60,62,3,2,1,4,61,53,1,0,0,0,61,56,1,0,0,0,62,65,1,0,0,0,63,61,1,0,0,0,
34 | 63,64,1,0,0,0,64,3,1,0,0,0,65,63,1,0,0,0,66,67,5,2,0,0,67,69,3,6,3,0,68,
35 | 70,3,4,2,0,69,68,1,0,0,0,69,70,1,0,0,0,70,81,1,0,0,0,71,72,5,4,0,0,72,74,
36 | 3,8,4,0,73,75,3,4,2,0,74,73,1,0,0,0,74,75,1,0,0,0,75,81,1,0,0,0,76,78,3,
37 | 10,5,0,77,79,3,4,2,0,78,77,1,0,0,0,78,79,1,0,0,0,79,81,1,0,0,0,80,66,1,0,
38 | 0,0,80,71,1,0,0,0,80,76,1,0,0,0,81,5,1,0,0,0,82,86,5,5,0,0,83,86,3,28,14,
39 | 0,84,86,3,10,5,0,85,82,1,0,0,0,85,83,1,0,0,0,85,84,1,0,0,0,86,7,1,0,0,0,
40 | 87,91,5,5,0,0,88,91,5,44,0,0,89,91,3,28,14,0,90,87,1,0,0,0,90,88,1,0,0,0,
41 | 90,89,1,0,0,0,91,9,1,0,0,0,92,93,5,29,0,0,93,94,3,12,6,0,94,95,5,30,0,0,
42 | 95,11,1,0,0,0,96,105,3,18,9,0,97,105,3,16,8,0,98,105,3,20,10,0,99,105,5,
43 | 5,0,0,100,105,5,44,0,0,101,105,5,45,0,0,102,105,3,28,14,0,103,105,3,14,7,
44 | 0,104,96,1,0,0,0,104,97,1,0,0,0,104,98,1,0,0,0,104,99,1,0,0,0,104,100,1,
45 | 0,0,0,104,101,1,0,0,0,104,102,1,0,0,0,104,103,1,0,0,0,105,13,1,0,0,0,106,
46 | 107,5,35,0,0,107,108,5,33,0,0,108,109,3,24,12,0,109,110,5,34,0,0,110,15,
47 | 1,0,0,0,111,114,5,44,0,0,112,113,5,32,0,0,113,115,5,44,0,0,114,112,1,0,0,
48 | 0,115,116,1,0,0,0,116,114,1,0,0,0,116,117,1,0,0,0,117,17,1,0,0,0,118,121,
49 | 5,45,0,0,119,120,5,32,0,0,120,122,5,45,0,0,121,119,1,0,0,0,122,123,1,0,0,
50 | 0,123,121,1,0,0,0,123,124,1,0,0,0,124,133,1,0,0,0,125,128,3,28,14,0,126,
51 | 127,5,32,0,0,127,129,3,28,14,0,128,126,1,0,0,0,129,130,1,0,0,0,130,128,1,
52 | 0,0,0,130,131,1,0,0,0,131,133,1,0,0,0,132,118,1,0,0,0,132,125,1,0,0,0,133,
53 | 19,1,0,0,0,134,136,5,44,0,0,135,134,1,0,0,0,135,136,1,0,0,0,136,137,1,0,
54 | 0,0,137,139,5,31,0,0,138,140,5,44,0,0,139,138,1,0,0,0,139,140,1,0,0,0,140,
55 | 145,1,0,0,0,141,143,5,31,0,0,142,144,5,44,0,0,143,142,1,0,0,0,143,144,1,
56 | 0,0,0,144,146,1,0,0,0,145,141,1,0,0,0,145,146,1,0,0,0,146,21,1,0,0,0,147,
57 | 149,5,40,0,0,148,150,5,39,0,0,149,148,1,0,0,0,149,150,1,0,0,0,150,23,1,0,
58 | 0,0,151,152,6,12,-1,0,152,153,5,22,0,0,153,154,5,33,0,0,154,155,3,24,12,
59 | 0,155,156,5,34,0,0,156,177,1,0,0,0,157,158,5,33,0,0,158,159,3,24,12,0,159,
60 | 160,5,34,0,0,160,177,1,0,0,0,161,162,3,2,1,0,162,163,7,2,0,0,163,164,3,2,
61 | 1,0,164,177,1,0,0,0,165,166,3,2,1,0,166,167,5,13,0,0,167,168,3,22,11,0,168,
62 | 177,1,0,0,0,169,170,3,2,1,0,170,171,5,21,0,0,171,177,1,0,0,0,172,177,3,26,
63 | 13,0,173,177,5,24,0,0,174,177,5,25,0,0,175,177,5,26,0,0,176,151,1,0,0,0,
64 | 176,157,1,0,0,0,176,161,1,0,0,0,176,165,1,0,0,0,176,169,1,0,0,0,176,172,
65 | 1,0,0,0,176,173,1,0,0,0,176,174,1,0,0,0,176,175,1,0,0,0,177,183,1,0,0,0,
66 | 178,179,10,8,0,0,179,180,7,3,0,0,180,182,3,24,12,9,181,178,1,0,0,0,182,185,
67 | 1,0,0,0,183,181,1,0,0,0,183,184,1,0,0,0,184,25,1,0,0,0,185,183,1,0,0,0,186,
68 | 188,7,4,0,0,187,189,3,4,2,0,188,187,1,0,0,0,188,189,1,0,0,0,189,27,1,0,0,
69 | 0,190,191,7,5,0,0,191,29,1,0,0,0,192,193,5,27,0,0,193,198,3,32,16,0,194,
70 | 195,5,32,0,0,195,197,3,32,16,0,196,194,1,0,0,0,197,200,1,0,0,0,198,196,1,
71 | 0,0,0,198,199,1,0,0,0,199,201,1,0,0,0,200,198,1,0,0,0,201,202,5,28,0,0,202,
72 | 206,1,0,0,0,203,204,5,27,0,0,204,206,5,28,0,0,205,192,1,0,0,0,205,203,1,
73 | 0,0,0,206,31,1,0,0,0,207,208,5,45,0,0,208,209,5,31,0,0,209,210,3,36,18,0,
74 | 210,33,1,0,0,0,211,212,5,29,0,0,212,217,3,36,18,0,213,214,5,32,0,0,214,216,
75 | 3,36,18,0,215,213,1,0,0,0,216,219,1,0,0,0,217,215,1,0,0,0,217,218,1,0,0,
76 | 0,218,220,1,0,0,0,219,217,1,0,0,0,220,221,5,30,0,0,221,225,1,0,0,0,222,223,
77 | 5,29,0,0,223,225,5,30,0,0,224,211,1,0,0,0,224,222,1,0,0,0,225,35,1,0,0,0,
78 | 226,234,5,45,0,0,227,234,5,44,0,0,228,234,3,30,15,0,229,234,3,34,17,0,230,
79 | 234,5,24,0,0,231,234,5,25,0,0,232,234,5,26,0,0,233,226,1,0,0,0,233,227,1,
80 | 0,0,0,233,228,1,0,0,0,233,229,1,0,0,0,233,230,1,0,0,0,233,231,1,0,0,0,233,
81 | 232,1,0,0,0,234,37,1,0,0,0,29,40,51,58,61,63,69,74,78,80,85,90,104,116,123,
82 | 130,132,135,139,143,145,149,176,183,188,198,205,217,224,233];
83 |
84 |
85 | const atn = new antlr4.atn.ATNDeserializer().deserialize(serializedATN);
86 |
87 | const decisionsToDFA = atn.decisionToState.map( (ds, index) => new antlr4.dfa.DFA(ds, index) );
88 |
89 | const sharedContextCache = new antlr4.atn.PredictionContextCache();
90 |
91 | export default class JSONPathParser extends antlr4.Parser {
92 |
93 | static grammarFileName = "JSONPath.g4";
94 | static literalNames = [ null, "'@'", "'..'", "'$'", "'.'", "'*'", "'&&'",
95 | "'=='", "'>='", "'>'", "'<='", "'<'", "'!='",
96 | "'=~'", "' in '", "' nin '", "' subsetof '",
97 | "' anyof '", "' noneof '", "' sizeof '", "' size '",
98 | "' empty'", "'!'", "'||'", "'true'", "'false'",
99 | "'null'", "'{'", "'}'", "'['", "']'", "':'",
100 | "','", "'('", "')'", "'?'", "'- '", "'+'", "'/'" ];
101 | static symbolicNames = [ null, "CURRENT_VALUE", "DOTDOT", "ROOT_VALUE",
102 | "DOT", "STAR", "AND", "EQ", "GE", "GT", "LE",
103 | "LT", "NE", "REG", "IN", "NIN", "SUB", "ANY",
104 | "NON", "SIZO", "SIZ", "EMPT", "NOT", "OR",
105 | "TRUE", "FALSE", "NULL", "BRACE_LEFT", "BRACE_RIGHT",
106 | "BRACKET_LEFT", "BRACKET_RIGHT", "COLON", "COMMA",
107 | "PAREN_LEFT", "PAREN_RIGHT", "QUESTION", "MINUS_SP",
108 | "PLUS", "DIV", "REGEX_OPT", "REGEX_EXPR", "KEY",
109 | "SPECIAL_KEY", "WS", "NUMBER", "STRING" ];
110 | static ruleNames = [ "jsonpath", "filterarg", "subscript", "dotdotContent",
111 | "dotContent", "bracket", "bracketContent", "filterExpression",
112 | "indexes", "unions", "slices", "regex", "expression",
113 | "filterpath", "identifier", "obj", "pair", "array",
114 | "value" ];
115 |
116 | constructor(input) {
117 | super(input);
118 | this._interp = new antlr4.atn.ParserATNSimulator(this, atn, decisionsToDFA, sharedContextCache);
119 | this.ruleNames = JSONPathParser.ruleNames;
120 | this.literalNames = JSONPathParser.literalNames;
121 | this.symbolicNames = JSONPathParser.symbolicNames;
122 | }
123 |
124 | sempred(localctx, ruleIndex, predIndex) {
125 | switch(ruleIndex) {
126 | case 1:
127 | return this.filterarg_sempred(localctx, predIndex);
128 | case 12:
129 | return this.expression_sempred(localctx, predIndex);
130 | default:
131 | throw "No predicate with index:" + ruleIndex;
132 | }
133 | }
134 |
135 | filterarg_sempred(localctx, predIndex) {
136 | switch(predIndex) {
137 | case 0:
138 | return this.precpred(this._ctx, 4);
139 | case 1:
140 | return this.precpred(this._ctx, 3);
141 | default:
142 | throw "No predicate with index:" + predIndex;
143 | }
144 | };
145 |
146 | expression_sempred(localctx, predIndex) {
147 | switch(predIndex) {
148 | case 2:
149 | return this.precpred(this._ctx, 8);
150 | default:
151 | throw "No predicate with index:" + predIndex;
152 | }
153 | };
154 |
155 |
156 |
157 |
158 | jsonpath() {
159 | let localctx = new JsonpathContext(this, this._ctx, this.state);
160 | this.enterRule(localctx, 0, JSONPathParser.RULE_jsonpath);
161 | var _la = 0;
162 | try {
163 | this.enterOuterAlt(localctx, 1);
164 | this.state = 38;
165 | this.match(JSONPathParser.ROOT_VALUE);
166 | this.state = 40;
167 | this._errHandler.sync(this);
168 | _la = this._input.LA(1);
169 | if((((_la) & ~0x1f) === 0 && ((1 << _la) & 536870932) !== 0)) {
170 | this.state = 39;
171 | this.subscript();
172 | }
173 |
174 | this.state = 42;
175 | this.match(JSONPathParser.EOF);
176 | } catch (re) {
177 | if(re instanceof antlr4.error.RecognitionException) {
178 | localctx.exception = re;
179 | this._errHandler.reportError(this, re);
180 | this._errHandler.recover(this, re);
181 | } else {
182 | throw re;
183 | }
184 | } finally {
185 | this.exitRule();
186 | }
187 | return localctx;
188 | }
189 |
190 |
191 | filterarg(_p) {
192 | if(_p===undefined) {
193 | _p = 0;
194 | }
195 | const _parentctx = this._ctx;
196 | const _parentState = this.state;
197 | let localctx = new FilterargContext(this, this._ctx, _parentState);
198 | let _prevctx = localctx;
199 | const _startState = 2;
200 | this.enterRecursionRule(localctx, 2, JSONPathParser.RULE_filterarg, _p);
201 | var _la = 0;
202 | try {
203 | this.enterOuterAlt(localctx, 1);
204 | this.state = 51;
205 | this._errHandler.sync(this);
206 | switch(this._input.LA(1)) {
207 | case 33:
208 | this.state = 45;
209 | this.match(JSONPathParser.PAREN_LEFT);
210 | this.state = 46;
211 | this.filterarg(0);
212 | this.state = 47;
213 | this.match(JSONPathParser.PAREN_RIGHT);
214 | break;
215 | case 24:
216 | case 25:
217 | case 26:
218 | case 27:
219 | case 29:
220 | case 44:
221 | case 45:
222 | this.state = 49;
223 | this.value();
224 | break;
225 | case 1:
226 | case 3:
227 | this.state = 50;
228 | this.filterpath();
229 | break;
230 | default:
231 | throw new antlr4.error.NoViableAltException(this);
232 | }
233 | this._ctx.stop = this._input.LT(-1);
234 | this.state = 63;
235 | this._errHandler.sync(this);
236 | var _alt = this._interp.adaptivePredict(this._input,4,this._ctx)
237 | while(_alt!=2 && _alt!=antlr4.atn.ATN.INVALID_ALT_NUMBER) {
238 | if(_alt===1) {
239 | if(this._parseListeners!==null) {
240 | this.triggerExitRuleEvent();
241 | }
242 | _prevctx = localctx;
243 | this.state = 61;
244 | this._errHandler.sync(this);
245 | var la_ = this._interp.adaptivePredict(this._input,3,this._ctx);
246 | switch(la_) {
247 | case 1:
248 | localctx = new FilterargContext(this, _parentctx, _parentState);
249 | this.pushNewRecursionContext(localctx, _startState, JSONPathParser.RULE_filterarg);
250 | this.state = 53;
251 | if (!( this.precpred(this._ctx, 4))) {
252 | throw new antlr4.error.FailedPredicateException(this, "this.precpred(this._ctx, 4)");
253 | }
254 | this.state = 54;
255 | _la = this._input.LA(1);
256 | if(!(_la===5 || _la===38)) {
257 | this._errHandler.recoverInline(this);
258 | }
259 | else {
260 | this._errHandler.reportMatch(this);
261 | this.consume();
262 | }
263 | this.state = 55;
264 | this.filterarg(5);
265 | break;
266 |
267 | case 2:
268 | localctx = new FilterargContext(this, _parentctx, _parentState);
269 | this.pushNewRecursionContext(localctx, _startState, JSONPathParser.RULE_filterarg);
270 | this.state = 56;
271 | if (!( this.precpred(this._ctx, 3))) {
272 | throw new antlr4.error.FailedPredicateException(this, "this.precpred(this._ctx, 3)");
273 | }
274 | this.state = 58;
275 | this._errHandler.sync(this);
276 | _la = this._input.LA(1);
277 | if(_la===36 || _la===37) {
278 | this.state = 57;
279 | _la = this._input.LA(1);
280 | if(!(_la===36 || _la===37)) {
281 | this._errHandler.recoverInline(this);
282 | }
283 | else {
284 | this._errHandler.reportMatch(this);
285 | this.consume();
286 | }
287 | }
288 |
289 | this.state = 60;
290 | this.filterarg(4);
291 | break;
292 |
293 | }
294 | }
295 | this.state = 65;
296 | this._errHandler.sync(this);
297 | _alt = this._interp.adaptivePredict(this._input,4,this._ctx);
298 | }
299 |
300 | } catch( error) {
301 | if(error instanceof antlr4.error.RecognitionException) {
302 | localctx.exception = error;
303 | this._errHandler.reportError(this, error);
304 | this._errHandler.recover(this, error);
305 | } else {
306 | throw error;
307 | }
308 | } finally {
309 | this.unrollRecursionContexts(_parentctx)
310 | }
311 | return localctx;
312 | }
313 |
314 |
315 |
316 | subscript() {
317 | let localctx = new SubscriptContext(this, this._ctx, this.state);
318 | this.enterRule(localctx, 4, JSONPathParser.RULE_subscript);
319 | try {
320 | this.state = 80;
321 | this._errHandler.sync(this);
322 | switch(this._input.LA(1)) {
323 | case 2:
324 | this.enterOuterAlt(localctx, 1);
325 | this.state = 66;
326 | this.match(JSONPathParser.DOTDOT);
327 | this.state = 67;
328 | this.dotdotContent();
329 | this.state = 69;
330 | this._errHandler.sync(this);
331 | var la_ = this._interp.adaptivePredict(this._input,5,this._ctx);
332 | if(la_===1) {
333 | this.state = 68;
334 | this.subscript();
335 |
336 | }
337 | break;
338 | case 4:
339 | this.enterOuterAlt(localctx, 2);
340 | this.state = 71;
341 | this.match(JSONPathParser.DOT);
342 | this.state = 72;
343 | this.dotContent();
344 | this.state = 74;
345 | this._errHandler.sync(this);
346 | var la_ = this._interp.adaptivePredict(this._input,6,this._ctx);
347 | if(la_===1) {
348 | this.state = 73;
349 | this.subscript();
350 |
351 | }
352 | break;
353 | case 29:
354 | this.enterOuterAlt(localctx, 3);
355 | this.state = 76;
356 | this.bracket();
357 | this.state = 78;
358 | this._errHandler.sync(this);
359 | var la_ = this._interp.adaptivePredict(this._input,7,this._ctx);
360 | if(la_===1) {
361 | this.state = 77;
362 | this.subscript();
363 |
364 | }
365 | break;
366 | default:
367 | throw new antlr4.error.NoViableAltException(this);
368 | }
369 | } catch (re) {
370 | if(re instanceof antlr4.error.RecognitionException) {
371 | localctx.exception = re;
372 | this._errHandler.reportError(this, re);
373 | this._errHandler.recover(this, re);
374 | } else {
375 | throw re;
376 | }
377 | } finally {
378 | this.exitRule();
379 | }
380 | return localctx;
381 | }
382 |
383 |
384 |
385 | dotdotContent() {
386 | let localctx = new DotdotContentContext(this, this._ctx, this.state);
387 | this.enterRule(localctx, 6, JSONPathParser.RULE_dotdotContent);
388 | try {
389 | this.state = 85;
390 | this._errHandler.sync(this);
391 | switch(this._input.LA(1)) {
392 | case 5:
393 | this.enterOuterAlt(localctx, 1);
394 | this.state = 82;
395 | this.match(JSONPathParser.STAR);
396 | break;
397 | case 24:
398 | case 25:
399 | case 26:
400 | case 41:
401 | case 42:
402 | this.enterOuterAlt(localctx, 2);
403 | this.state = 83;
404 | this.identifier();
405 | break;
406 | case 29:
407 | this.enterOuterAlt(localctx, 3);
408 | this.state = 84;
409 | this.bracket();
410 | break;
411 | default:
412 | throw new antlr4.error.NoViableAltException(this);
413 | }
414 | } catch (re) {
415 | if(re instanceof antlr4.error.RecognitionException) {
416 | localctx.exception = re;
417 | this._errHandler.reportError(this, re);
418 | this._errHandler.recover(this, re);
419 | } else {
420 | throw re;
421 | }
422 | } finally {
423 | this.exitRule();
424 | }
425 | return localctx;
426 | }
427 |
428 |
429 |
430 | dotContent() {
431 | let localctx = new DotContentContext(this, this._ctx, this.state);
432 | this.enterRule(localctx, 8, JSONPathParser.RULE_dotContent);
433 | try {
434 | this.state = 90;
435 | this._errHandler.sync(this);
436 | switch(this._input.LA(1)) {
437 | case 5:
438 | this.enterOuterAlt(localctx, 1);
439 | this.state = 87;
440 | this.match(JSONPathParser.STAR);
441 | break;
442 | case 44:
443 | this.enterOuterAlt(localctx, 2);
444 | this.state = 88;
445 | this.match(JSONPathParser.NUMBER);
446 | break;
447 | case 24:
448 | case 25:
449 | case 26:
450 | case 41:
451 | case 42:
452 | this.enterOuterAlt(localctx, 3);
453 | this.state = 89;
454 | this.identifier();
455 | break;
456 | default:
457 | throw new antlr4.error.NoViableAltException(this);
458 | }
459 | } catch (re) {
460 | if(re instanceof antlr4.error.RecognitionException) {
461 | localctx.exception = re;
462 | this._errHandler.reportError(this, re);
463 | this._errHandler.recover(this, re);
464 | } else {
465 | throw re;
466 | }
467 | } finally {
468 | this.exitRule();
469 | }
470 | return localctx;
471 | }
472 |
473 |
474 |
475 | bracket() {
476 | let localctx = new BracketContext(this, this._ctx, this.state);
477 | this.enterRule(localctx, 10, JSONPathParser.RULE_bracket);
478 | try {
479 | this.enterOuterAlt(localctx, 1);
480 | this.state = 92;
481 | this.match(JSONPathParser.BRACKET_LEFT);
482 | this.state = 93;
483 | this.bracketContent();
484 | this.state = 94;
485 | this.match(JSONPathParser.BRACKET_RIGHT);
486 | } catch (re) {
487 | if(re instanceof antlr4.error.RecognitionException) {
488 | localctx.exception = re;
489 | this._errHandler.reportError(this, re);
490 | this._errHandler.recover(this, re);
491 | } else {
492 | throw re;
493 | }
494 | } finally {
495 | this.exitRule();
496 | }
497 | return localctx;
498 | }
499 |
500 |
501 |
502 | bracketContent() {
503 | let localctx = new BracketContentContext(this, this._ctx, this.state);
504 | this.enterRule(localctx, 12, JSONPathParser.RULE_bracketContent);
505 | try {
506 | this.state = 104;
507 | this._errHandler.sync(this);
508 | var la_ = this._interp.adaptivePredict(this._input,11,this._ctx);
509 | switch(la_) {
510 | case 1:
511 | this.enterOuterAlt(localctx, 1);
512 | this.state = 96;
513 | this.unions();
514 | break;
515 |
516 | case 2:
517 | this.enterOuterAlt(localctx, 2);
518 | this.state = 97;
519 | this.indexes();
520 | break;
521 |
522 | case 3:
523 | this.enterOuterAlt(localctx, 3);
524 | this.state = 98;
525 | this.slices();
526 | break;
527 |
528 | case 4:
529 | this.enterOuterAlt(localctx, 4);
530 | this.state = 99;
531 | this.match(JSONPathParser.STAR);
532 | break;
533 |
534 | case 5:
535 | this.enterOuterAlt(localctx, 5);
536 | this.state = 100;
537 | this.match(JSONPathParser.NUMBER);
538 | break;
539 |
540 | case 6:
541 | this.enterOuterAlt(localctx, 6);
542 | this.state = 101;
543 | this.match(JSONPathParser.STRING);
544 | break;
545 |
546 | case 7:
547 | this.enterOuterAlt(localctx, 7);
548 | this.state = 102;
549 | this.identifier();
550 | break;
551 |
552 | case 8:
553 | this.enterOuterAlt(localctx, 8);
554 | this.state = 103;
555 | this.filterExpression();
556 | break;
557 |
558 | }
559 | } catch (re) {
560 | if(re instanceof antlr4.error.RecognitionException) {
561 | localctx.exception = re;
562 | this._errHandler.reportError(this, re);
563 | this._errHandler.recover(this, re);
564 | } else {
565 | throw re;
566 | }
567 | } finally {
568 | this.exitRule();
569 | }
570 | return localctx;
571 | }
572 |
573 |
574 |
575 | filterExpression() {
576 | let localctx = new FilterExpressionContext(this, this._ctx, this.state);
577 | this.enterRule(localctx, 14, JSONPathParser.RULE_filterExpression);
578 | try {
579 | this.enterOuterAlt(localctx, 1);
580 | this.state = 106;
581 | this.match(JSONPathParser.QUESTION);
582 | this.state = 107;
583 | this.match(JSONPathParser.PAREN_LEFT);
584 | this.state = 108;
585 | this.expression(0);
586 | this.state = 109;
587 | this.match(JSONPathParser.PAREN_RIGHT);
588 | } catch (re) {
589 | if(re instanceof antlr4.error.RecognitionException) {
590 | localctx.exception = re;
591 | this._errHandler.reportError(this, re);
592 | this._errHandler.recover(this, re);
593 | } else {
594 | throw re;
595 | }
596 | } finally {
597 | this.exitRule();
598 | }
599 | return localctx;
600 | }
601 |
602 |
603 |
604 | indexes() {
605 | let localctx = new IndexesContext(this, this._ctx, this.state);
606 | this.enterRule(localctx, 16, JSONPathParser.RULE_indexes);
607 | var _la = 0;
608 | try {
609 | this.enterOuterAlt(localctx, 1);
610 | this.state = 111;
611 | this.match(JSONPathParser.NUMBER);
612 | this.state = 114;
613 | this._errHandler.sync(this);
614 | _la = this._input.LA(1);
615 | do {
616 | this.state = 112;
617 | this.match(JSONPathParser.COMMA);
618 | this.state = 113;
619 | this.match(JSONPathParser.NUMBER);
620 | this.state = 116;
621 | this._errHandler.sync(this);
622 | _la = this._input.LA(1);
623 | } while(_la===32);
624 | } catch (re) {
625 | if(re instanceof antlr4.error.RecognitionException) {
626 | localctx.exception = re;
627 | this._errHandler.reportError(this, re);
628 | this._errHandler.recover(this, re);
629 | } else {
630 | throw re;
631 | }
632 | } finally {
633 | this.exitRule();
634 | }
635 | return localctx;
636 | }
637 |
638 |
639 |
640 | unions() {
641 | let localctx = new UnionsContext(this, this._ctx, this.state);
642 | this.enterRule(localctx, 18, JSONPathParser.RULE_unions);
643 | var _la = 0;
644 | try {
645 | this.state = 132;
646 | this._errHandler.sync(this);
647 | switch(this._input.LA(1)) {
648 | case 45:
649 | this.enterOuterAlt(localctx, 1);
650 | this.state = 118;
651 | this.match(JSONPathParser.STRING);
652 | this.state = 121;
653 | this._errHandler.sync(this);
654 | _la = this._input.LA(1);
655 | do {
656 | this.state = 119;
657 | this.match(JSONPathParser.COMMA);
658 | this.state = 120;
659 | this.match(JSONPathParser.STRING);
660 | this.state = 123;
661 | this._errHandler.sync(this);
662 | _la = this._input.LA(1);
663 | } while(_la===32);
664 | break;
665 | case 24:
666 | case 25:
667 | case 26:
668 | case 41:
669 | case 42:
670 | this.enterOuterAlt(localctx, 2);
671 | this.state = 125;
672 | this.identifier();
673 | this.state = 128;
674 | this._errHandler.sync(this);
675 | _la = this._input.LA(1);
676 | do {
677 | this.state = 126;
678 | this.match(JSONPathParser.COMMA);
679 | this.state = 127;
680 | this.identifier();
681 | this.state = 130;
682 | this._errHandler.sync(this);
683 | _la = this._input.LA(1);
684 | } while(_la===32);
685 | break;
686 | default:
687 | throw new antlr4.error.NoViableAltException(this);
688 | }
689 | } catch (re) {
690 | if(re instanceof antlr4.error.RecognitionException) {
691 | localctx.exception = re;
692 | this._errHandler.reportError(this, re);
693 | this._errHandler.recover(this, re);
694 | } else {
695 | throw re;
696 | }
697 | } finally {
698 | this.exitRule();
699 | }
700 | return localctx;
701 | }
702 |
703 |
704 |
705 | slices() {
706 | let localctx = new SlicesContext(this, this._ctx, this.state);
707 | this.enterRule(localctx, 20, JSONPathParser.RULE_slices);
708 | var _la = 0;
709 | try {
710 | this.enterOuterAlt(localctx, 1);
711 | this.state = 135;
712 | this._errHandler.sync(this);
713 | _la = this._input.LA(1);
714 | if(_la===44) {
715 | this.state = 134;
716 | this.match(JSONPathParser.NUMBER);
717 | }
718 |
719 | this.state = 137;
720 | this.match(JSONPathParser.COLON);
721 | this.state = 139;
722 | this._errHandler.sync(this);
723 | _la = this._input.LA(1);
724 | if(_la===44) {
725 | this.state = 138;
726 | this.match(JSONPathParser.NUMBER);
727 | }
728 |
729 | this.state = 145;
730 | this._errHandler.sync(this);
731 | _la = this._input.LA(1);
732 | if(_la===31) {
733 | this.state = 141;
734 | this.match(JSONPathParser.COLON);
735 | this.state = 143;
736 | this._errHandler.sync(this);
737 | _la = this._input.LA(1);
738 | if(_la===44) {
739 | this.state = 142;
740 | this.match(JSONPathParser.NUMBER);
741 | }
742 |
743 | }
744 |
745 | } catch (re) {
746 | if(re instanceof antlr4.error.RecognitionException) {
747 | localctx.exception = re;
748 | this._errHandler.reportError(this, re);
749 | this._errHandler.recover(this, re);
750 | } else {
751 | throw re;
752 | }
753 | } finally {
754 | this.exitRule();
755 | }
756 | return localctx;
757 | }
758 |
759 |
760 |
761 | regex() {
762 | let localctx = new RegexContext(this, this._ctx, this.state);
763 | this.enterRule(localctx, 22, JSONPathParser.RULE_regex);
764 | try {
765 | this.enterOuterAlt(localctx, 1);
766 | this.state = 147;
767 | this.match(JSONPathParser.REGEX_EXPR);
768 | this.state = 149;
769 | this._errHandler.sync(this);
770 | var la_ = this._interp.adaptivePredict(this._input,20,this._ctx);
771 | if(la_===1) {
772 | this.state = 148;
773 | this.match(JSONPathParser.REGEX_OPT);
774 |
775 | }
776 | } catch (re) {
777 | if(re instanceof antlr4.error.RecognitionException) {
778 | localctx.exception = re;
779 | this._errHandler.reportError(this, re);
780 | this._errHandler.recover(this, re);
781 | } else {
782 | throw re;
783 | }
784 | } finally {
785 | this.exitRule();
786 | }
787 | return localctx;
788 | }
789 |
790 |
791 | expression(_p) {
792 | if(_p===undefined) {
793 | _p = 0;
794 | }
795 | const _parentctx = this._ctx;
796 | const _parentState = this.state;
797 | let localctx = new ExpressionContext(this, this._ctx, _parentState);
798 | let _prevctx = localctx;
799 | const _startState = 24;
800 | this.enterRecursionRule(localctx, 24, JSONPathParser.RULE_expression, _p);
801 | var _la = 0;
802 | try {
803 | this.enterOuterAlt(localctx, 1);
804 | this.state = 176;
805 | this._errHandler.sync(this);
806 | var la_ = this._interp.adaptivePredict(this._input,21,this._ctx);
807 | switch(la_) {
808 | case 1:
809 | this.state = 152;
810 | this.match(JSONPathParser.NOT);
811 | this.state = 153;
812 | this.match(JSONPathParser.PAREN_LEFT);
813 | this.state = 154;
814 | this.expression(0);
815 | this.state = 155;
816 | this.match(JSONPathParser.PAREN_RIGHT);
817 | break;
818 |
819 | case 2:
820 | this.state = 157;
821 | this.match(JSONPathParser.PAREN_LEFT);
822 | this.state = 158;
823 | this.expression(0);
824 | this.state = 159;
825 | this.match(JSONPathParser.PAREN_RIGHT);
826 | break;
827 |
828 | case 3:
829 | this.state = 161;
830 | this.filterarg(0);
831 | this.state = 162;
832 | _la = this._input.LA(1);
833 | if(!((((_la) & ~0x1f) === 0 && ((1 << _la) & 2088832) !== 0))) {
834 | this._errHandler.recoverInline(this);
835 | }
836 | else {
837 | this._errHandler.reportMatch(this);
838 | this.consume();
839 | }
840 | this.state = 163;
841 | this.filterarg(0);
842 | break;
843 |
844 | case 4:
845 | this.state = 165;
846 | this.filterarg(0);
847 | this.state = 166;
848 | this.match(JSONPathParser.REG);
849 | this.state = 167;
850 | this.regex();
851 | break;
852 |
853 | case 5:
854 | this.state = 169;
855 | this.filterarg(0);
856 | this.state = 170;
857 | this.match(JSONPathParser.EMPT);
858 | break;
859 |
860 | case 6:
861 | this.state = 172;
862 | this.filterpath();
863 | break;
864 |
865 | case 7:
866 | this.state = 173;
867 | this.match(JSONPathParser.TRUE);
868 | break;
869 |
870 | case 8:
871 | this.state = 174;
872 | this.match(JSONPathParser.FALSE);
873 | break;
874 |
875 | case 9:
876 | this.state = 175;
877 | this.match(JSONPathParser.NULL);
878 | break;
879 |
880 | }
881 | this._ctx.stop = this._input.LT(-1);
882 | this.state = 183;
883 | this._errHandler.sync(this);
884 | var _alt = this._interp.adaptivePredict(this._input,22,this._ctx)
885 | while(_alt!=2 && _alt!=antlr4.atn.ATN.INVALID_ALT_NUMBER) {
886 | if(_alt===1) {
887 | if(this._parseListeners!==null) {
888 | this.triggerExitRuleEvent();
889 | }
890 | _prevctx = localctx;
891 | localctx = new ExpressionContext(this, _parentctx, _parentState);
892 | this.pushNewRecursionContext(localctx, _startState, JSONPathParser.RULE_expression);
893 | this.state = 178;
894 | if (!( this.precpred(this._ctx, 8))) {
895 | throw new antlr4.error.FailedPredicateException(this, "this.precpred(this._ctx, 8)");
896 | }
897 | this.state = 179;
898 | _la = this._input.LA(1);
899 | if(!(_la===6 || _la===23)) {
900 | this._errHandler.recoverInline(this);
901 | }
902 | else {
903 | this._errHandler.reportMatch(this);
904 | this.consume();
905 | }
906 | this.state = 180;
907 | this.expression(9);
908 | }
909 | this.state = 185;
910 | this._errHandler.sync(this);
911 | _alt = this._interp.adaptivePredict(this._input,22,this._ctx);
912 | }
913 |
914 | } catch( error) {
915 | if(error instanceof antlr4.error.RecognitionException) {
916 | localctx.exception = error;
917 | this._errHandler.reportError(this, error);
918 | this._errHandler.recover(this, error);
919 | } else {
920 | throw error;
921 | }
922 | } finally {
923 | this.unrollRecursionContexts(_parentctx)
924 | }
925 | return localctx;
926 | }
927 |
928 |
929 |
930 | filterpath() {
931 | let localctx = new FilterpathContext(this, this._ctx, this.state);
932 | this.enterRule(localctx, 26, JSONPathParser.RULE_filterpath);
933 | var _la = 0;
934 | try {
935 | this.enterOuterAlt(localctx, 1);
936 | this.state = 186;
937 | _la = this._input.LA(1);
938 | if(!(_la===1 || _la===3)) {
939 | this._errHandler.recoverInline(this);
940 | }
941 | else {
942 | this._errHandler.reportMatch(this);
943 | this.consume();
944 | }
945 | this.state = 188;
946 | this._errHandler.sync(this);
947 | var la_ = this._interp.adaptivePredict(this._input,23,this._ctx);
948 | if(la_===1) {
949 | this.state = 187;
950 | this.subscript();
951 |
952 | }
953 | } catch (re) {
954 | if(re instanceof antlr4.error.RecognitionException) {
955 | localctx.exception = re;
956 | this._errHandler.reportError(this, re);
957 | this._errHandler.recover(this, re);
958 | } else {
959 | throw re;
960 | }
961 | } finally {
962 | this.exitRule();
963 | }
964 | return localctx;
965 | }
966 |
967 |
968 |
969 | identifier() {
970 | let localctx = new IdentifierContext(this, this._ctx, this.state);
971 | this.enterRule(localctx, 28, JSONPathParser.RULE_identifier);
972 | var _la = 0;
973 | try {
974 | this.enterOuterAlt(localctx, 1);
975 | this.state = 190;
976 | _la = this._input.LA(1);
977 | if(!(((((_la - 24)) & ~0x1f) === 0 && ((1 << (_la - 24)) & 393223) !== 0))) {
978 | this._errHandler.recoverInline(this);
979 | }
980 | else {
981 | this._errHandler.reportMatch(this);
982 | this.consume();
983 | }
984 | } catch (re) {
985 | if(re instanceof antlr4.error.RecognitionException) {
986 | localctx.exception = re;
987 | this._errHandler.reportError(this, re);
988 | this._errHandler.recover(this, re);
989 | } else {
990 | throw re;
991 | }
992 | } finally {
993 | this.exitRule();
994 | }
995 | return localctx;
996 | }
997 |
998 |
999 |
1000 | obj() {
1001 | let localctx = new ObjContext(this, this._ctx, this.state);
1002 | this.enterRule(localctx, 30, JSONPathParser.RULE_obj);
1003 | var _la = 0;
1004 | try {
1005 | this.state = 205;
1006 | this._errHandler.sync(this);
1007 | var la_ = this._interp.adaptivePredict(this._input,25,this._ctx);
1008 | switch(la_) {
1009 | case 1:
1010 | this.enterOuterAlt(localctx, 1);
1011 | this.state = 192;
1012 | this.match(JSONPathParser.BRACE_LEFT);
1013 | this.state = 193;
1014 | this.pair();
1015 | this.state = 198;
1016 | this._errHandler.sync(this);
1017 | _la = this._input.LA(1);
1018 | while(_la===32) {
1019 | this.state = 194;
1020 | this.match(JSONPathParser.COMMA);
1021 | this.state = 195;
1022 | this.pair();
1023 | this.state = 200;
1024 | this._errHandler.sync(this);
1025 | _la = this._input.LA(1);
1026 | }
1027 | this.state = 201;
1028 | this.match(JSONPathParser.BRACE_RIGHT);
1029 | break;
1030 |
1031 | case 2:
1032 | this.enterOuterAlt(localctx, 2);
1033 | this.state = 203;
1034 | this.match(JSONPathParser.BRACE_LEFT);
1035 | this.state = 204;
1036 | this.match(JSONPathParser.BRACE_RIGHT);
1037 | break;
1038 |
1039 | }
1040 | } catch (re) {
1041 | if(re instanceof antlr4.error.RecognitionException) {
1042 | localctx.exception = re;
1043 | this._errHandler.reportError(this, re);
1044 | this._errHandler.recover(this, re);
1045 | } else {
1046 | throw re;
1047 | }
1048 | } finally {
1049 | this.exitRule();
1050 | }
1051 | return localctx;
1052 | }
1053 |
1054 |
1055 |
1056 | pair() {
1057 | let localctx = new PairContext(this, this._ctx, this.state);
1058 | this.enterRule(localctx, 32, JSONPathParser.RULE_pair);
1059 | try {
1060 | this.enterOuterAlt(localctx, 1);
1061 | this.state = 207;
1062 | this.match(JSONPathParser.STRING);
1063 | this.state = 208;
1064 | this.match(JSONPathParser.COLON);
1065 | this.state = 209;
1066 | this.value();
1067 | } catch (re) {
1068 | if(re instanceof antlr4.error.RecognitionException) {
1069 | localctx.exception = re;
1070 | this._errHandler.reportError(this, re);
1071 | this._errHandler.recover(this, re);
1072 | } else {
1073 | throw re;
1074 | }
1075 | } finally {
1076 | this.exitRule();
1077 | }
1078 | return localctx;
1079 | }
1080 |
1081 |
1082 |
1083 | array() {
1084 | let localctx = new ArrayContext(this, this._ctx, this.state);
1085 | this.enterRule(localctx, 34, JSONPathParser.RULE_array);
1086 | var _la = 0;
1087 | try {
1088 | this.state = 224;
1089 | this._errHandler.sync(this);
1090 | var la_ = this._interp.adaptivePredict(this._input,27,this._ctx);
1091 | switch(la_) {
1092 | case 1:
1093 | this.enterOuterAlt(localctx, 1);
1094 | this.state = 211;
1095 | this.match(JSONPathParser.BRACKET_LEFT);
1096 | this.state = 212;
1097 | this.value();
1098 | this.state = 217;
1099 | this._errHandler.sync(this);
1100 | _la = this._input.LA(1);
1101 | while(_la===32) {
1102 | this.state = 213;
1103 | this.match(JSONPathParser.COMMA);
1104 | this.state = 214;
1105 | this.value();
1106 | this.state = 219;
1107 | this._errHandler.sync(this);
1108 | _la = this._input.LA(1);
1109 | }
1110 | this.state = 220;
1111 | this.match(JSONPathParser.BRACKET_RIGHT);
1112 | break;
1113 |
1114 | case 2:
1115 | this.enterOuterAlt(localctx, 2);
1116 | this.state = 222;
1117 | this.match(JSONPathParser.BRACKET_LEFT);
1118 | this.state = 223;
1119 | this.match(JSONPathParser.BRACKET_RIGHT);
1120 | break;
1121 |
1122 | }
1123 | } catch (re) {
1124 | if(re instanceof antlr4.error.RecognitionException) {
1125 | localctx.exception = re;
1126 | this._errHandler.reportError(this, re);
1127 | this._errHandler.recover(this, re);
1128 | } else {
1129 | throw re;
1130 | }
1131 | } finally {
1132 | this.exitRule();
1133 | }
1134 | return localctx;
1135 | }
1136 |
1137 |
1138 |
1139 | value() {
1140 | let localctx = new ValueContext(this, this._ctx, this.state);
1141 | this.enterRule(localctx, 36, JSONPathParser.RULE_value);
1142 | try {
1143 | this.state = 233;
1144 | this._errHandler.sync(this);
1145 | switch(this._input.LA(1)) {
1146 | case 45:
1147 | this.enterOuterAlt(localctx, 1);
1148 | this.state = 226;
1149 | this.match(JSONPathParser.STRING);
1150 | break;
1151 | case 44:
1152 | this.enterOuterAlt(localctx, 2);
1153 | this.state = 227;
1154 | this.match(JSONPathParser.NUMBER);
1155 | break;
1156 | case 27:
1157 | this.enterOuterAlt(localctx, 3);
1158 | this.state = 228;
1159 | this.obj();
1160 | break;
1161 | case 29:
1162 | this.enterOuterAlt(localctx, 4);
1163 | this.state = 229;
1164 | this.array();
1165 | break;
1166 | case 24:
1167 | this.enterOuterAlt(localctx, 5);
1168 | this.state = 230;
1169 | this.match(JSONPathParser.TRUE);
1170 | break;
1171 | case 25:
1172 | this.enterOuterAlt(localctx, 6);
1173 | this.state = 231;
1174 | this.match(JSONPathParser.FALSE);
1175 | break;
1176 | case 26:
1177 | this.enterOuterAlt(localctx, 7);
1178 | this.state = 232;
1179 | this.match(JSONPathParser.NULL);
1180 | break;
1181 | default:
1182 | throw new antlr4.error.NoViableAltException(this);
1183 | }
1184 | } catch (re) {
1185 | if(re instanceof antlr4.error.RecognitionException) {
1186 | localctx.exception = re;
1187 | this._errHandler.reportError(this, re);
1188 | this._errHandler.recover(this, re);
1189 | } else {
1190 | throw re;
1191 | }
1192 | } finally {
1193 | this.exitRule();
1194 | }
1195 | return localctx;
1196 | }
1197 |
1198 |
1199 | }
1200 |
1201 | JSONPathParser.EOF = antlr4.Token.EOF;
1202 | JSONPathParser.CURRENT_VALUE = 1;
1203 | JSONPathParser.DOTDOT = 2;
1204 | JSONPathParser.ROOT_VALUE = 3;
1205 | JSONPathParser.DOT = 4;
1206 | JSONPathParser.STAR = 5;
1207 | JSONPathParser.AND = 6;
1208 | JSONPathParser.EQ = 7;
1209 | JSONPathParser.GE = 8;
1210 | JSONPathParser.GT = 9;
1211 | JSONPathParser.LE = 10;
1212 | JSONPathParser.LT = 11;
1213 | JSONPathParser.NE = 12;
1214 | JSONPathParser.REG = 13;
1215 | JSONPathParser.IN = 14;
1216 | JSONPathParser.NIN = 15;
1217 | JSONPathParser.SUB = 16;
1218 | JSONPathParser.ANY = 17;
1219 | JSONPathParser.NON = 18;
1220 | JSONPathParser.SIZO = 19;
1221 | JSONPathParser.SIZ = 20;
1222 | JSONPathParser.EMPT = 21;
1223 | JSONPathParser.NOT = 22;
1224 | JSONPathParser.OR = 23;
1225 | JSONPathParser.TRUE = 24;
1226 | JSONPathParser.FALSE = 25;
1227 | JSONPathParser.NULL = 26;
1228 | JSONPathParser.BRACE_LEFT = 27;
1229 | JSONPathParser.BRACE_RIGHT = 28;
1230 | JSONPathParser.BRACKET_LEFT = 29;
1231 | JSONPathParser.BRACKET_RIGHT = 30;
1232 | JSONPathParser.COLON = 31;
1233 | JSONPathParser.COMMA = 32;
1234 | JSONPathParser.PAREN_LEFT = 33;
1235 | JSONPathParser.PAREN_RIGHT = 34;
1236 | JSONPathParser.QUESTION = 35;
1237 | JSONPathParser.MINUS_SP = 36;
1238 | JSONPathParser.PLUS = 37;
1239 | JSONPathParser.DIV = 38;
1240 | JSONPathParser.REGEX_OPT = 39;
1241 | JSONPathParser.REGEX_EXPR = 40;
1242 | JSONPathParser.KEY = 41;
1243 | JSONPathParser.SPECIAL_KEY = 42;
1244 | JSONPathParser.WS = 43;
1245 | JSONPathParser.NUMBER = 44;
1246 | JSONPathParser.STRING = 45;
1247 |
1248 | JSONPathParser.RULE_jsonpath = 0;
1249 | JSONPathParser.RULE_filterarg = 1;
1250 | JSONPathParser.RULE_subscript = 2;
1251 | JSONPathParser.RULE_dotdotContent = 3;
1252 | JSONPathParser.RULE_dotContent = 4;
1253 | JSONPathParser.RULE_bracket = 5;
1254 | JSONPathParser.RULE_bracketContent = 6;
1255 | JSONPathParser.RULE_filterExpression = 7;
1256 | JSONPathParser.RULE_indexes = 8;
1257 | JSONPathParser.RULE_unions = 9;
1258 | JSONPathParser.RULE_slices = 10;
1259 | JSONPathParser.RULE_regex = 11;
1260 | JSONPathParser.RULE_expression = 12;
1261 | JSONPathParser.RULE_filterpath = 13;
1262 | JSONPathParser.RULE_identifier = 14;
1263 | JSONPathParser.RULE_obj = 15;
1264 | JSONPathParser.RULE_pair = 16;
1265 | JSONPathParser.RULE_array = 17;
1266 | JSONPathParser.RULE_value = 18;
1267 |
1268 | class JsonpathContext extends antlr4.ParserRuleContext {
1269 |
1270 | constructor(parser, parent, invokingState) {
1271 | if(parent===undefined) {
1272 | parent = null;
1273 | }
1274 | if(invokingState===undefined || invokingState===null) {
1275 | invokingState = -1;
1276 | }
1277 | super(parent, invokingState);
1278 | this.parser = parser;
1279 | this.ruleIndex = JSONPathParser.RULE_jsonpath;
1280 | }
1281 |
1282 | ROOT_VALUE() {
1283 | return this.getToken(JSONPathParser.ROOT_VALUE, 0);
1284 | };
1285 |
1286 | EOF() {
1287 | return this.getToken(JSONPathParser.EOF, 0);
1288 | };
1289 |
1290 | subscript() {
1291 | return this.getTypedRuleContext(SubscriptContext,0);
1292 | };
1293 |
1294 | enterRule(listener) {
1295 | if(listener instanceof JSONPathListener ) {
1296 | listener.enterJsonpath(this);
1297 | }
1298 | }
1299 |
1300 | exitRule(listener) {
1301 | if(listener instanceof JSONPathListener ) {
1302 | listener.exitJsonpath(this);
1303 | }
1304 | }
1305 |
1306 |
1307 | }
1308 |
1309 |
1310 |
1311 | class FilterargContext extends antlr4.ParserRuleContext {
1312 |
1313 | constructor(parser, parent, invokingState) {
1314 | if(parent===undefined) {
1315 | parent = null;
1316 | }
1317 | if(invokingState===undefined || invokingState===null) {
1318 | invokingState = -1;
1319 | }
1320 | super(parent, invokingState);
1321 | this.parser = parser;
1322 | this.ruleIndex = JSONPathParser.RULE_filterarg;
1323 | }
1324 |
1325 | PAREN_LEFT() {
1326 | return this.getToken(JSONPathParser.PAREN_LEFT, 0);
1327 | };
1328 |
1329 | filterarg = function(i) {
1330 | if(i===undefined) {
1331 | i = null;
1332 | }
1333 | if(i===null) {
1334 | return this.getTypedRuleContexts(FilterargContext);
1335 | } else {
1336 | return this.getTypedRuleContext(FilterargContext,i);
1337 | }
1338 | };
1339 |
1340 | PAREN_RIGHT() {
1341 | return this.getToken(JSONPathParser.PAREN_RIGHT, 0);
1342 | };
1343 |
1344 | value() {
1345 | return this.getTypedRuleContext(ValueContext,0);
1346 | };
1347 |
1348 | filterpath() {
1349 | return this.getTypedRuleContext(FilterpathContext,0);
1350 | };
1351 |
1352 | STAR() {
1353 | return this.getToken(JSONPathParser.STAR, 0);
1354 | };
1355 |
1356 | DIV() {
1357 | return this.getToken(JSONPathParser.DIV, 0);
1358 | };
1359 |
1360 | PLUS() {
1361 | return this.getToken(JSONPathParser.PLUS, 0);
1362 | };
1363 |
1364 | MINUS_SP() {
1365 | return this.getToken(JSONPathParser.MINUS_SP, 0);
1366 | };
1367 |
1368 | enterRule(listener) {
1369 | if(listener instanceof JSONPathListener ) {
1370 | listener.enterFilterarg(this);
1371 | }
1372 | }
1373 |
1374 | exitRule(listener) {
1375 | if(listener instanceof JSONPathListener ) {
1376 | listener.exitFilterarg(this);
1377 | }
1378 | }
1379 |
1380 |
1381 | }
1382 |
1383 |
1384 |
1385 | class SubscriptContext extends antlr4.ParserRuleContext {
1386 |
1387 | constructor(parser, parent, invokingState) {
1388 | if(parent===undefined) {
1389 | parent = null;
1390 | }
1391 | if(invokingState===undefined || invokingState===null) {
1392 | invokingState = -1;
1393 | }
1394 | super(parent, invokingState);
1395 | this.parser = parser;
1396 | this.ruleIndex = JSONPathParser.RULE_subscript;
1397 | }
1398 |
1399 | DOTDOT() {
1400 | return this.getToken(JSONPathParser.DOTDOT, 0);
1401 | };
1402 |
1403 | dotdotContent() {
1404 | return this.getTypedRuleContext(DotdotContentContext,0);
1405 | };
1406 |
1407 | subscript() {
1408 | return this.getTypedRuleContext(SubscriptContext,0);
1409 | };
1410 |
1411 | DOT() {
1412 | return this.getToken(JSONPathParser.DOT, 0);
1413 | };
1414 |
1415 | dotContent() {
1416 | return this.getTypedRuleContext(DotContentContext,0);
1417 | };
1418 |
1419 | bracket() {
1420 | return this.getTypedRuleContext(BracketContext,0);
1421 | };
1422 |
1423 | enterRule(listener) {
1424 | if(listener instanceof JSONPathListener ) {
1425 | listener.enterSubscript(this);
1426 | }
1427 | }
1428 |
1429 | exitRule(listener) {
1430 | if(listener instanceof JSONPathListener ) {
1431 | listener.exitSubscript(this);
1432 | }
1433 | }
1434 |
1435 |
1436 | }
1437 |
1438 |
1439 |
1440 | class DotdotContentContext extends antlr4.ParserRuleContext {
1441 |
1442 | constructor(parser, parent, invokingState) {
1443 | if(parent===undefined) {
1444 | parent = null;
1445 | }
1446 | if(invokingState===undefined || invokingState===null) {
1447 | invokingState = -1;
1448 | }
1449 | super(parent, invokingState);
1450 | this.parser = parser;
1451 | this.ruleIndex = JSONPathParser.RULE_dotdotContent;
1452 | }
1453 |
1454 | STAR() {
1455 | return this.getToken(JSONPathParser.STAR, 0);
1456 | };
1457 |
1458 | identifier() {
1459 | return this.getTypedRuleContext(IdentifierContext,0);
1460 | };
1461 |
1462 | bracket() {
1463 | return this.getTypedRuleContext(BracketContext,0);
1464 | };
1465 |
1466 | enterRule(listener) {
1467 | if(listener instanceof JSONPathListener ) {
1468 | listener.enterDotdotContent(this);
1469 | }
1470 | }
1471 |
1472 | exitRule(listener) {
1473 | if(listener instanceof JSONPathListener ) {
1474 | listener.exitDotdotContent(this);
1475 | }
1476 | }
1477 |
1478 |
1479 | }
1480 |
1481 |
1482 |
1483 | class DotContentContext extends antlr4.ParserRuleContext {
1484 |
1485 | constructor(parser, parent, invokingState) {
1486 | if(parent===undefined) {
1487 | parent = null;
1488 | }
1489 | if(invokingState===undefined || invokingState===null) {
1490 | invokingState = -1;
1491 | }
1492 | super(parent, invokingState);
1493 | this.parser = parser;
1494 | this.ruleIndex = JSONPathParser.RULE_dotContent;
1495 | }
1496 |
1497 | STAR() {
1498 | return this.getToken(JSONPathParser.STAR, 0);
1499 | };
1500 |
1501 | NUMBER() {
1502 | return this.getToken(JSONPathParser.NUMBER, 0);
1503 | };
1504 |
1505 | identifier() {
1506 | return this.getTypedRuleContext(IdentifierContext,0);
1507 | };
1508 |
1509 | enterRule(listener) {
1510 | if(listener instanceof JSONPathListener ) {
1511 | listener.enterDotContent(this);
1512 | }
1513 | }
1514 |
1515 | exitRule(listener) {
1516 | if(listener instanceof JSONPathListener ) {
1517 | listener.exitDotContent(this);
1518 | }
1519 | }
1520 |
1521 |
1522 | }
1523 |
1524 |
1525 |
1526 | class BracketContext extends antlr4.ParserRuleContext {
1527 |
1528 | constructor(parser, parent, invokingState) {
1529 | if(parent===undefined) {
1530 | parent = null;
1531 | }
1532 | if(invokingState===undefined || invokingState===null) {
1533 | invokingState = -1;
1534 | }
1535 | super(parent, invokingState);
1536 | this.parser = parser;
1537 | this.ruleIndex = JSONPathParser.RULE_bracket;
1538 | }
1539 |
1540 | BRACKET_LEFT() {
1541 | return this.getToken(JSONPathParser.BRACKET_LEFT, 0);
1542 | };
1543 |
1544 | bracketContent() {
1545 | return this.getTypedRuleContext(BracketContentContext,0);
1546 | };
1547 |
1548 | BRACKET_RIGHT() {
1549 | return this.getToken(JSONPathParser.BRACKET_RIGHT, 0);
1550 | };
1551 |
1552 | enterRule(listener) {
1553 | if(listener instanceof JSONPathListener ) {
1554 | listener.enterBracket(this);
1555 | }
1556 | }
1557 |
1558 | exitRule(listener) {
1559 | if(listener instanceof JSONPathListener ) {
1560 | listener.exitBracket(this);
1561 | }
1562 | }
1563 |
1564 |
1565 | }
1566 |
1567 |
1568 |
1569 | class BracketContentContext extends antlr4.ParserRuleContext {
1570 |
1571 | constructor(parser, parent, invokingState) {
1572 | if(parent===undefined) {
1573 | parent = null;
1574 | }
1575 | if(invokingState===undefined || invokingState===null) {
1576 | invokingState = -1;
1577 | }
1578 | super(parent, invokingState);
1579 | this.parser = parser;
1580 | this.ruleIndex = JSONPathParser.RULE_bracketContent;
1581 | }
1582 |
1583 | unions() {
1584 | return this.getTypedRuleContext(UnionsContext,0);
1585 | };
1586 |
1587 | indexes() {
1588 | return this.getTypedRuleContext(IndexesContext,0);
1589 | };
1590 |
1591 | slices() {
1592 | return this.getTypedRuleContext(SlicesContext,0);
1593 | };
1594 |
1595 | STAR() {
1596 | return this.getToken(JSONPathParser.STAR, 0);
1597 | };
1598 |
1599 | NUMBER() {
1600 | return this.getToken(JSONPathParser.NUMBER, 0);
1601 | };
1602 |
1603 | STRING() {
1604 | return this.getToken(JSONPathParser.STRING, 0);
1605 | };
1606 |
1607 | identifier() {
1608 | return this.getTypedRuleContext(IdentifierContext,0);
1609 | };
1610 |
1611 | filterExpression() {
1612 | return this.getTypedRuleContext(FilterExpressionContext,0);
1613 | };
1614 |
1615 | enterRule(listener) {
1616 | if(listener instanceof JSONPathListener ) {
1617 | listener.enterBracketContent(this);
1618 | }
1619 | }
1620 |
1621 | exitRule(listener) {
1622 | if(listener instanceof JSONPathListener ) {
1623 | listener.exitBracketContent(this);
1624 | }
1625 | }
1626 |
1627 |
1628 | }
1629 |
1630 |
1631 |
1632 | class FilterExpressionContext extends antlr4.ParserRuleContext {
1633 |
1634 | constructor(parser, parent, invokingState) {
1635 | if(parent===undefined) {
1636 | parent = null;
1637 | }
1638 | if(invokingState===undefined || invokingState===null) {
1639 | invokingState = -1;
1640 | }
1641 | super(parent, invokingState);
1642 | this.parser = parser;
1643 | this.ruleIndex = JSONPathParser.RULE_filterExpression;
1644 | }
1645 |
1646 | QUESTION() {
1647 | return this.getToken(JSONPathParser.QUESTION, 0);
1648 | };
1649 |
1650 | PAREN_LEFT() {
1651 | return this.getToken(JSONPathParser.PAREN_LEFT, 0);
1652 | };
1653 |
1654 | expression() {
1655 | return this.getTypedRuleContext(ExpressionContext,0);
1656 | };
1657 |
1658 | PAREN_RIGHT() {
1659 | return this.getToken(JSONPathParser.PAREN_RIGHT, 0);
1660 | };
1661 |
1662 | enterRule(listener) {
1663 | if(listener instanceof JSONPathListener ) {
1664 | listener.enterFilterExpression(this);
1665 | }
1666 | }
1667 |
1668 | exitRule(listener) {
1669 | if(listener instanceof JSONPathListener ) {
1670 | listener.exitFilterExpression(this);
1671 | }
1672 | }
1673 |
1674 |
1675 | }
1676 |
1677 |
1678 |
1679 | class IndexesContext extends antlr4.ParserRuleContext {
1680 |
1681 | constructor(parser, parent, invokingState) {
1682 | if(parent===undefined) {
1683 | parent = null;
1684 | }
1685 | if(invokingState===undefined || invokingState===null) {
1686 | invokingState = -1;
1687 | }
1688 | super(parent, invokingState);
1689 | this.parser = parser;
1690 | this.ruleIndex = JSONPathParser.RULE_indexes;
1691 | }
1692 |
1693 | NUMBER = function(i) {
1694 | if(i===undefined) {
1695 | i = null;
1696 | }
1697 | if(i===null) {
1698 | return this.getTokens(JSONPathParser.NUMBER);
1699 | } else {
1700 | return this.getToken(JSONPathParser.NUMBER, i);
1701 | }
1702 | };
1703 |
1704 |
1705 | COMMA = function(i) {
1706 | if(i===undefined) {
1707 | i = null;
1708 | }
1709 | if(i===null) {
1710 | return this.getTokens(JSONPathParser.COMMA);
1711 | } else {
1712 | return this.getToken(JSONPathParser.COMMA, i);
1713 | }
1714 | };
1715 |
1716 |
1717 | enterRule(listener) {
1718 | if(listener instanceof JSONPathListener ) {
1719 | listener.enterIndexes(this);
1720 | }
1721 | }
1722 |
1723 | exitRule(listener) {
1724 | if(listener instanceof JSONPathListener ) {
1725 | listener.exitIndexes(this);
1726 | }
1727 | }
1728 |
1729 |
1730 | }
1731 |
1732 |
1733 |
1734 | class UnionsContext extends antlr4.ParserRuleContext {
1735 |
1736 | constructor(parser, parent, invokingState) {
1737 | if(parent===undefined) {
1738 | parent = null;
1739 | }
1740 | if(invokingState===undefined || invokingState===null) {
1741 | invokingState = -1;
1742 | }
1743 | super(parent, invokingState);
1744 | this.parser = parser;
1745 | this.ruleIndex = JSONPathParser.RULE_unions;
1746 | }
1747 |
1748 | STRING = function(i) {
1749 | if(i===undefined) {
1750 | i = null;
1751 | }
1752 | if(i===null) {
1753 | return this.getTokens(JSONPathParser.STRING);
1754 | } else {
1755 | return this.getToken(JSONPathParser.STRING, i);
1756 | }
1757 | };
1758 |
1759 |
1760 | COMMA = function(i) {
1761 | if(i===undefined) {
1762 | i = null;
1763 | }
1764 | if(i===null) {
1765 | return this.getTokens(JSONPathParser.COMMA);
1766 | } else {
1767 | return this.getToken(JSONPathParser.COMMA, i);
1768 | }
1769 | };
1770 |
1771 |
1772 | identifier = function(i) {
1773 | if(i===undefined) {
1774 | i = null;
1775 | }
1776 | if(i===null) {
1777 | return this.getTypedRuleContexts(IdentifierContext);
1778 | } else {
1779 | return this.getTypedRuleContext(IdentifierContext,i);
1780 | }
1781 | };
1782 |
1783 | enterRule(listener) {
1784 | if(listener instanceof JSONPathListener ) {
1785 | listener.enterUnions(this);
1786 | }
1787 | }
1788 |
1789 | exitRule(listener) {
1790 | if(listener instanceof JSONPathListener ) {
1791 | listener.exitUnions(this);
1792 | }
1793 | }
1794 |
1795 |
1796 | }
1797 |
1798 |
1799 |
1800 | class SlicesContext extends antlr4.ParserRuleContext {
1801 |
1802 | constructor(parser, parent, invokingState) {
1803 | if(parent===undefined) {
1804 | parent = null;
1805 | }
1806 | if(invokingState===undefined || invokingState===null) {
1807 | invokingState = -1;
1808 | }
1809 | super(parent, invokingState);
1810 | this.parser = parser;
1811 | this.ruleIndex = JSONPathParser.RULE_slices;
1812 | }
1813 |
1814 | COLON = function(i) {
1815 | if(i===undefined) {
1816 | i = null;
1817 | }
1818 | if(i===null) {
1819 | return this.getTokens(JSONPathParser.COLON);
1820 | } else {
1821 | return this.getToken(JSONPathParser.COLON, i);
1822 | }
1823 | };
1824 |
1825 |
1826 | NUMBER = function(i) {
1827 | if(i===undefined) {
1828 | i = null;
1829 | }
1830 | if(i===null) {
1831 | return this.getTokens(JSONPathParser.NUMBER);
1832 | } else {
1833 | return this.getToken(JSONPathParser.NUMBER, i);
1834 | }
1835 | };
1836 |
1837 |
1838 | enterRule(listener) {
1839 | if(listener instanceof JSONPathListener ) {
1840 | listener.enterSlices(this);
1841 | }
1842 | }
1843 |
1844 | exitRule(listener) {
1845 | if(listener instanceof JSONPathListener ) {
1846 | listener.exitSlices(this);
1847 | }
1848 | }
1849 |
1850 |
1851 | }
1852 |
1853 |
1854 |
1855 | class RegexContext extends antlr4.ParserRuleContext {
1856 |
1857 | constructor(parser, parent, invokingState) {
1858 | if(parent===undefined) {
1859 | parent = null;
1860 | }
1861 | if(invokingState===undefined || invokingState===null) {
1862 | invokingState = -1;
1863 | }
1864 | super(parent, invokingState);
1865 | this.parser = parser;
1866 | this.ruleIndex = JSONPathParser.RULE_regex;
1867 | }
1868 |
1869 | REGEX_EXPR() {
1870 | return this.getToken(JSONPathParser.REGEX_EXPR, 0);
1871 | };
1872 |
1873 | REGEX_OPT() {
1874 | return this.getToken(JSONPathParser.REGEX_OPT, 0);
1875 | };
1876 |
1877 | enterRule(listener) {
1878 | if(listener instanceof JSONPathListener ) {
1879 | listener.enterRegex(this);
1880 | }
1881 | }
1882 |
1883 | exitRule(listener) {
1884 | if(listener instanceof JSONPathListener ) {
1885 | listener.exitRegex(this);
1886 | }
1887 | }
1888 |
1889 |
1890 | }
1891 |
1892 |
1893 |
1894 | class ExpressionContext extends antlr4.ParserRuleContext {
1895 |
1896 | constructor(parser, parent, invokingState) {
1897 | if(parent===undefined) {
1898 | parent = null;
1899 | }
1900 | if(invokingState===undefined || invokingState===null) {
1901 | invokingState = -1;
1902 | }
1903 | super(parent, invokingState);
1904 | this.parser = parser;
1905 | this.ruleIndex = JSONPathParser.RULE_expression;
1906 | }
1907 |
1908 | NOT() {
1909 | return this.getToken(JSONPathParser.NOT, 0);
1910 | };
1911 |
1912 | PAREN_LEFT() {
1913 | return this.getToken(JSONPathParser.PAREN_LEFT, 0);
1914 | };
1915 |
1916 | expression = function(i) {
1917 | if(i===undefined) {
1918 | i = null;
1919 | }
1920 | if(i===null) {
1921 | return this.getTypedRuleContexts(ExpressionContext);
1922 | } else {
1923 | return this.getTypedRuleContext(ExpressionContext,i);
1924 | }
1925 | };
1926 |
1927 | PAREN_RIGHT() {
1928 | return this.getToken(JSONPathParser.PAREN_RIGHT, 0);
1929 | };
1930 |
1931 | filterarg = function(i) {
1932 | if(i===undefined) {
1933 | i = null;
1934 | }
1935 | if(i===null) {
1936 | return this.getTypedRuleContexts(FilterargContext);
1937 | } else {
1938 | return this.getTypedRuleContext(FilterargContext,i);
1939 | }
1940 | };
1941 |
1942 | EQ() {
1943 | return this.getToken(JSONPathParser.EQ, 0);
1944 | };
1945 |
1946 | NE() {
1947 | return this.getToken(JSONPathParser.NE, 0);
1948 | };
1949 |
1950 | LT() {
1951 | return this.getToken(JSONPathParser.LT, 0);
1952 | };
1953 |
1954 | LE() {
1955 | return this.getToken(JSONPathParser.LE, 0);
1956 | };
1957 |
1958 | GT() {
1959 | return this.getToken(JSONPathParser.GT, 0);
1960 | };
1961 |
1962 | GE() {
1963 | return this.getToken(JSONPathParser.GE, 0);
1964 | };
1965 |
1966 | IN() {
1967 | return this.getToken(JSONPathParser.IN, 0);
1968 | };
1969 |
1970 | NIN() {
1971 | return this.getToken(JSONPathParser.NIN, 0);
1972 | };
1973 |
1974 | SUB() {
1975 | return this.getToken(JSONPathParser.SUB, 0);
1976 | };
1977 |
1978 | ANY() {
1979 | return this.getToken(JSONPathParser.ANY, 0);
1980 | };
1981 |
1982 | SIZO() {
1983 | return this.getToken(JSONPathParser.SIZO, 0);
1984 | };
1985 |
1986 | NON() {
1987 | return this.getToken(JSONPathParser.NON, 0);
1988 | };
1989 |
1990 | SIZ() {
1991 | return this.getToken(JSONPathParser.SIZ, 0);
1992 | };
1993 |
1994 | REG() {
1995 | return this.getToken(JSONPathParser.REG, 0);
1996 | };
1997 |
1998 | regex() {
1999 | return this.getTypedRuleContext(RegexContext,0);
2000 | };
2001 |
2002 | EMPT() {
2003 | return this.getToken(JSONPathParser.EMPT, 0);
2004 | };
2005 |
2006 | filterpath() {
2007 | return this.getTypedRuleContext(FilterpathContext,0);
2008 | };
2009 |
2010 | TRUE() {
2011 | return this.getToken(JSONPathParser.TRUE, 0);
2012 | };
2013 |
2014 | FALSE() {
2015 | return this.getToken(JSONPathParser.FALSE, 0);
2016 | };
2017 |
2018 | NULL() {
2019 | return this.getToken(JSONPathParser.NULL, 0);
2020 | };
2021 |
2022 | AND() {
2023 | return this.getToken(JSONPathParser.AND, 0);
2024 | };
2025 |
2026 | OR() {
2027 | return this.getToken(JSONPathParser.OR, 0);
2028 | };
2029 |
2030 | enterRule(listener) {
2031 | if(listener instanceof JSONPathListener ) {
2032 | listener.enterExpression(this);
2033 | }
2034 | }
2035 |
2036 | exitRule(listener) {
2037 | if(listener instanceof JSONPathListener ) {
2038 | listener.exitExpression(this);
2039 | }
2040 | }
2041 |
2042 |
2043 | }
2044 |
2045 |
2046 |
2047 | class FilterpathContext extends antlr4.ParserRuleContext {
2048 |
2049 | constructor(parser, parent, invokingState) {
2050 | if(parent===undefined) {
2051 | parent = null;
2052 | }
2053 | if(invokingState===undefined || invokingState===null) {
2054 | invokingState = -1;
2055 | }
2056 | super(parent, invokingState);
2057 | this.parser = parser;
2058 | this.ruleIndex = JSONPathParser.RULE_filterpath;
2059 | }
2060 |
2061 | ROOT_VALUE() {
2062 | return this.getToken(JSONPathParser.ROOT_VALUE, 0);
2063 | };
2064 |
2065 | CURRENT_VALUE() {
2066 | return this.getToken(JSONPathParser.CURRENT_VALUE, 0);
2067 | };
2068 |
2069 | subscript() {
2070 | return this.getTypedRuleContext(SubscriptContext,0);
2071 | };
2072 |
2073 | enterRule(listener) {
2074 | if(listener instanceof JSONPathListener ) {
2075 | listener.enterFilterpath(this);
2076 | }
2077 | }
2078 |
2079 | exitRule(listener) {
2080 | if(listener instanceof JSONPathListener ) {
2081 | listener.exitFilterpath(this);
2082 | }
2083 | }
2084 |
2085 |
2086 | }
2087 |
2088 |
2089 |
2090 | class IdentifierContext extends antlr4.ParserRuleContext {
2091 |
2092 | constructor(parser, parent, invokingState) {
2093 | if(parent===undefined) {
2094 | parent = null;
2095 | }
2096 | if(invokingState===undefined || invokingState===null) {
2097 | invokingState = -1;
2098 | }
2099 | super(parent, invokingState);
2100 | this.parser = parser;
2101 | this.ruleIndex = JSONPathParser.RULE_identifier;
2102 | }
2103 |
2104 | KEY() {
2105 | return this.getToken(JSONPathParser.KEY, 0);
2106 | };
2107 |
2108 | SPECIAL_KEY() {
2109 | return this.getToken(JSONPathParser.SPECIAL_KEY, 0);
2110 | };
2111 |
2112 | TRUE() {
2113 | return this.getToken(JSONPathParser.TRUE, 0);
2114 | };
2115 |
2116 | FALSE() {
2117 | return this.getToken(JSONPathParser.FALSE, 0);
2118 | };
2119 |
2120 | NULL() {
2121 | return this.getToken(JSONPathParser.NULL, 0);
2122 | };
2123 |
2124 | enterRule(listener) {
2125 | if(listener instanceof JSONPathListener ) {
2126 | listener.enterIdentifier(this);
2127 | }
2128 | }
2129 |
2130 | exitRule(listener) {
2131 | if(listener instanceof JSONPathListener ) {
2132 | listener.exitIdentifier(this);
2133 | }
2134 | }
2135 |
2136 |
2137 | }
2138 |
2139 |
2140 |
2141 | class ObjContext extends antlr4.ParserRuleContext {
2142 |
2143 | constructor(parser, parent, invokingState) {
2144 | if(parent===undefined) {
2145 | parent = null;
2146 | }
2147 | if(invokingState===undefined || invokingState===null) {
2148 | invokingState = -1;
2149 | }
2150 | super(parent, invokingState);
2151 | this.parser = parser;
2152 | this.ruleIndex = JSONPathParser.RULE_obj;
2153 | }
2154 |
2155 | BRACE_LEFT() {
2156 | return this.getToken(JSONPathParser.BRACE_LEFT, 0);
2157 | };
2158 |
2159 | pair = function(i) {
2160 | if(i===undefined) {
2161 | i = null;
2162 | }
2163 | if(i===null) {
2164 | return this.getTypedRuleContexts(PairContext);
2165 | } else {
2166 | return this.getTypedRuleContext(PairContext,i);
2167 | }
2168 | };
2169 |
2170 | BRACE_RIGHT() {
2171 | return this.getToken(JSONPathParser.BRACE_RIGHT, 0);
2172 | };
2173 |
2174 | COMMA = function(i) {
2175 | if(i===undefined) {
2176 | i = null;
2177 | }
2178 | if(i===null) {
2179 | return this.getTokens(JSONPathParser.COMMA);
2180 | } else {
2181 | return this.getToken(JSONPathParser.COMMA, i);
2182 | }
2183 | };
2184 |
2185 |
2186 | enterRule(listener) {
2187 | if(listener instanceof JSONPathListener ) {
2188 | listener.enterObj(this);
2189 | }
2190 | }
2191 |
2192 | exitRule(listener) {
2193 | if(listener instanceof JSONPathListener ) {
2194 | listener.exitObj(this);
2195 | }
2196 | }
2197 |
2198 |
2199 | }
2200 |
2201 |
2202 |
2203 | class PairContext extends antlr4.ParserRuleContext {
2204 |
2205 | constructor(parser, parent, invokingState) {
2206 | if(parent===undefined) {
2207 | parent = null;
2208 | }
2209 | if(invokingState===undefined || invokingState===null) {
2210 | invokingState = -1;
2211 | }
2212 | super(parent, invokingState);
2213 | this.parser = parser;
2214 | this.ruleIndex = JSONPathParser.RULE_pair;
2215 | }
2216 |
2217 | STRING() {
2218 | return this.getToken(JSONPathParser.STRING, 0);
2219 | };
2220 |
2221 | COLON() {
2222 | return this.getToken(JSONPathParser.COLON, 0);
2223 | };
2224 |
2225 | value() {
2226 | return this.getTypedRuleContext(ValueContext,0);
2227 | };
2228 |
2229 | enterRule(listener) {
2230 | if(listener instanceof JSONPathListener ) {
2231 | listener.enterPair(this);
2232 | }
2233 | }
2234 |
2235 | exitRule(listener) {
2236 | if(listener instanceof JSONPathListener ) {
2237 | listener.exitPair(this);
2238 | }
2239 | }
2240 |
2241 |
2242 | }
2243 |
2244 |
2245 |
2246 | class ArrayContext extends antlr4.ParserRuleContext {
2247 |
2248 | constructor(parser, parent, invokingState) {
2249 | if(parent===undefined) {
2250 | parent = null;
2251 | }
2252 | if(invokingState===undefined || invokingState===null) {
2253 | invokingState = -1;
2254 | }
2255 | super(parent, invokingState);
2256 | this.parser = parser;
2257 | this.ruleIndex = JSONPathParser.RULE_array;
2258 | }
2259 |
2260 | BRACKET_LEFT() {
2261 | return this.getToken(JSONPathParser.BRACKET_LEFT, 0);
2262 | };
2263 |
2264 | value = function(i) {
2265 | if(i===undefined) {
2266 | i = null;
2267 | }
2268 | if(i===null) {
2269 | return this.getTypedRuleContexts(ValueContext);
2270 | } else {
2271 | return this.getTypedRuleContext(ValueContext,i);
2272 | }
2273 | };
2274 |
2275 | BRACKET_RIGHT() {
2276 | return this.getToken(JSONPathParser.BRACKET_RIGHT, 0);
2277 | };
2278 |
2279 | COMMA = function(i) {
2280 | if(i===undefined) {
2281 | i = null;
2282 | }
2283 | if(i===null) {
2284 | return this.getTokens(JSONPathParser.COMMA);
2285 | } else {
2286 | return this.getToken(JSONPathParser.COMMA, i);
2287 | }
2288 | };
2289 |
2290 |
2291 | enterRule(listener) {
2292 | if(listener instanceof JSONPathListener ) {
2293 | listener.enterArray(this);
2294 | }
2295 | }
2296 |
2297 | exitRule(listener) {
2298 | if(listener instanceof JSONPathListener ) {
2299 | listener.exitArray(this);
2300 | }
2301 | }
2302 |
2303 |
2304 | }
2305 |
2306 |
2307 |
2308 | class ValueContext extends antlr4.ParserRuleContext {
2309 |
2310 | constructor(parser, parent, invokingState) {
2311 | if(parent===undefined) {
2312 | parent = null;
2313 | }
2314 | if(invokingState===undefined || invokingState===null) {
2315 | invokingState = -1;
2316 | }
2317 | super(parent, invokingState);
2318 | this.parser = parser;
2319 | this.ruleIndex = JSONPathParser.RULE_value;
2320 | }
2321 |
2322 | STRING() {
2323 | return this.getToken(JSONPathParser.STRING, 0);
2324 | };
2325 |
2326 | NUMBER() {
2327 | return this.getToken(JSONPathParser.NUMBER, 0);
2328 | };
2329 |
2330 | obj() {
2331 | return this.getTypedRuleContext(ObjContext,0);
2332 | };
2333 |
2334 | array() {
2335 | return this.getTypedRuleContext(ArrayContext,0);
2336 | };
2337 |
2338 | TRUE() {
2339 | return this.getToken(JSONPathParser.TRUE, 0);
2340 | };
2341 |
2342 | FALSE() {
2343 | return this.getToken(JSONPathParser.FALSE, 0);
2344 | };
2345 |
2346 | NULL() {
2347 | return this.getToken(JSONPathParser.NULL, 0);
2348 | };
2349 |
2350 | enterRule(listener) {
2351 | if(listener instanceof JSONPathListener ) {
2352 | listener.enterValue(this);
2353 | }
2354 | }
2355 |
2356 | exitRule(listener) {
2357 | if(listener instanceof JSONPathListener ) {
2358 | listener.exitValue(this);
2359 | }
2360 | }
2361 |
2362 |
2363 | }
2364 |
2365 |
2366 |
2367 |
2368 | JSONPathParser.JsonpathContext = JsonpathContext;
2369 | JSONPathParser.FilterargContext = FilterargContext;
2370 | JSONPathParser.SubscriptContext = SubscriptContext;
2371 | JSONPathParser.DotdotContentContext = DotdotContentContext;
2372 | JSONPathParser.DotContentContext = DotContentContext;
2373 | JSONPathParser.BracketContext = BracketContext;
2374 | JSONPathParser.BracketContentContext = BracketContentContext;
2375 | JSONPathParser.FilterExpressionContext = FilterExpressionContext;
2376 | JSONPathParser.IndexesContext = IndexesContext;
2377 | JSONPathParser.UnionsContext = UnionsContext;
2378 | JSONPathParser.SlicesContext = SlicesContext;
2379 | JSONPathParser.RegexContext = RegexContext;
2380 | JSONPathParser.ExpressionContext = ExpressionContext;
2381 | JSONPathParser.FilterpathContext = FilterpathContext;
2382 | JSONPathParser.IdentifierContext = IdentifierContext;
2383 | JSONPathParser.ObjContext = ObjContext;
2384 | JSONPathParser.PairContext = PairContext;
2385 | JSONPathParser.ArrayContext = ArrayContext;
2386 | JSONPathParser.ValueContext = ValueContext;
2387 |
--------------------------------------------------------------------------------
/src/parser/parse.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-explicit-any */
2 | /* eslint-disable @typescript-eslint/no-unused-vars */
3 |
4 | import antlr4 from 'antlr4';
5 | import { JSONPathSyntaxError } from './errors';
6 | import JSONPathLexer from './generated/JSONPathLexer';
7 | import JSONPathParser from './generated/JSONPathParser';
8 | import Listener from './Listener';
9 | import { Root } from './types';
10 |
11 | const customErrorListener = {
12 | syntaxError: (
13 | _recognizer: antlr4.Recognizer,
14 | _offendingSymbol: any,
15 | line: number,
16 | charPositionInLine: number,
17 | msg: string,
18 | _e: any,
19 | ): void => {
20 | throw new JSONPathSyntaxError(line, charPositionInLine, msg);
21 | },
22 | reportAmbiguity: function (
23 | _recognizer: antlr4.Recognizer,
24 | _dfa: any,
25 | _startIndex: number,
26 | _stopIndex: number,
27 | _exact: any,
28 | _ambigAlts: any,
29 | _configs: any,
30 | ): void {
31 | return;
32 | },
33 | reportAttemptingFullContext: function (
34 | _recognizer: antlr4.Recognizer,
35 | _dfa: any,
36 | _startIndex: number,
37 | _stopIndex: number,
38 | _conflictingAlts: any,
39 | _configs: any,
40 | ): void {
41 | return;
42 | },
43 | reportContextSensitivity: function (
44 | _recognizer: antlr4.Recognizer,
45 | _dfa: any,
46 | _startIndex: number,
47 | _stopIndex: number,
48 | _conflictingAlts: any,
49 | _configs: any,
50 | ): void {
51 | return;
52 | },
53 | };
54 |
55 | export function parseInternal(input: string): Root {
56 | const inputStream = new antlr4.InputStream(input);
57 | const lexer = new JSONPathLexer(inputStream);
58 | const tokenStream = new antlr4.CommonTokenStream(lexer);
59 | const parser = new JSONPathParser(tokenStream);
60 |
61 | parser.removeErrorListeners();
62 | parser.addErrorListener(customErrorListener);
63 |
64 | const listener = new Listener();
65 | parser.buildParseTrees = true;
66 |
67 | const tree = parser.jsonpath();
68 |
69 | // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
70 | // @ts-ignore
71 | antlr4.tree.ParseTreeWalker.DEFAULT.walk(listener, tree);
72 |
73 | return listener.getTree();
74 | }
75 |
76 | export type ParseOptions = {
77 | hideExceptions?: boolean;
78 | };
79 |
80 | export function parse(input: string, options: ParseOptions = {}): Root | null {
81 | try {
82 | const tree = parseInternal(input);
83 | return tree;
84 | } catch (e) {
85 | if (!options.hideExceptions) {
86 | throw e;
87 | }
88 | return null;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/parser/stringify.ts:
--------------------------------------------------------------------------------
1 | import { Comparator, JsonPathElement, LogicalExpression, Operation } from './types';
2 |
3 | const OPERATOR: Record = {
4 | eq: '==',
5 | ne: '!=',
6 | lt: '<',
7 | le: '<=',
8 | gt: '>',
9 | ge: '>=',
10 | in: 'in',
11 | reg: '=~',
12 | nin: 'nin',
13 | subsetof: 'subsetof',
14 | anyof: 'anyof',
15 | noneof: 'noneof',
16 | empty: 'empty',
17 | sizeof: 'sizeof',
18 | size: 'size',
19 | };
20 |
21 | const COMP_OPERATOR: Record = {
22 | plus: '+',
23 | minus: '-',
24 | multi: '*',
25 | div: '/',
26 | '': '',
27 | };
28 |
29 | const EXPR_OPERATOR: Record = {
30 | and: '&&',
31 | or: '||',
32 | };
33 |
34 | export function stringify(input: JsonPathElement | null): string {
35 | if (input === null) {
36 | return '';
37 | }
38 |
39 | switch (input.type) {
40 | case 'root': {
41 | return '$' + stringify(input.next);
42 | }
43 | case 'current': {
44 | return '@' + stringify(input.next);
45 | }
46 | case 'dot': {
47 | return '.' + stringify(input.value);
48 | }
49 | case 'dotdot': {
50 | const res = stringify(input.value);
51 | return '..' + res;
52 | }
53 | case 'bracketExpression':
54 | case 'bracketMember': {
55 | return '[' + stringify(input.value) + ']';
56 | }
57 | case 'subscript': {
58 | return stringify(input.value) + stringify(input.next);
59 | }
60 | case 'identifier': {
61 | return input.value;
62 | }
63 | case 'wildcard': {
64 | return '*';
65 | }
66 | case 'indexes': {
67 | return input.values.map(stringify).join(', ');
68 | }
69 | case 'unions': {
70 | return input.values.map(stringify).join(', ');
71 | }
72 | case 'stringLiteral': {
73 | return `"${input.value}"`;
74 | }
75 | case 'numericLiteral': {
76 | return `${input.value}`;
77 | }
78 | case 'notExpression': {
79 | return '!(' + stringify(input.value) + ')';
80 | }
81 | case 'value': {
82 | if (input.subtype === 'regex') {
83 | return `${input.value}${input.opts}`;
84 | }
85 | return JSON.stringify(input.value);
86 | }
87 | case 'filterExpression': {
88 | return '?(' + stringify(input.value) + ')';
89 | }
90 | case 'groupOperation': {
91 | return '(' + stringify(input.value) + ')';
92 | }
93 | case 'groupExpression': {
94 | return '(' + stringify(input.value) + ')';
95 | }
96 | case 'operation': {
97 | return stringify(input.left) + ' ' + COMP_OPERATOR[input.operator] + ' ' + stringify(input.right);
98 | }
99 | case 'comparator': {
100 | return stringify(input.left) + ` ${OPERATOR[input.operator]} ` + stringify(input.right);
101 | }
102 | case 'logicalExpression': {
103 | return stringify(input.left) + ` ${EXPR_OPERATOR[input.operator]} ` + stringify(input.right);
104 | }
105 | case 'slices': {
106 | return `${input.start !== null ? input.start : ''}:${input.end !== null ? input.end : ''}${
107 | input.step !== null ? ':' + input.step : ''
108 | }`;
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/parser/types.ts:
--------------------------------------------------------------------------------
1 | export type Root = {
2 | type: 'root';
3 | next: Subscript | null;
4 | };
5 |
6 | export type Current = {
7 | type: 'current';
8 | next: Subscript | null;
9 | };
10 |
11 | export type ValueObject = { type: 'value'; value: Record; subtype: 'object' };
12 | export type ValueArray = { type: 'value'; value: unknown[]; subtype: 'array' };
13 | export type ValueString = { type: 'value'; value: string; subtype: 'string' };
14 | export type ValueBoolean = { type: 'value'; value: boolean; subtype: 'boolean' };
15 | export type ValueNumber = { type: 'value'; value: number; subtype: 'number' };
16 | export type ValueNull = { type: 'value'; value: null; subtype: 'null' };
17 | export type ValueRegex = { type: 'value'; value: `/${string}/`; subtype: 'regex'; opts: string };
18 |
19 | export type Value = ValueString | ValueBoolean | ValueNumber | ValueNull | ValueArray | ValueObject | ValueRegex;
20 |
21 | export type NotExpression = {
22 | type: 'notExpression';
23 | value: FilterExpressionContent;
24 | };
25 |
26 | export type GroupExpression = {
27 | type: 'groupExpression';
28 | value: FilterExpressionContent;
29 | };
30 |
31 | export type GroupOperation = {
32 | type: 'groupOperation';
33 | value: OperationContent;
34 | };
35 |
36 | export type LogicalExpression = {
37 | type: 'logicalExpression';
38 | operator: 'or' | 'and';
39 | left: FilterExpressionContent;
40 | right: FilterExpressionContent;
41 | };
42 |
43 | export type Slices = {
44 | type: 'slices';
45 | start: number | null;
46 | end: number | null;
47 | step: number | null;
48 | };
49 |
50 | export type Comparator =
51 | | {
52 | type: 'comparator';
53 | operator:
54 | | 'eq'
55 | | 'ne'
56 | | 'lt'
57 | | 'le'
58 | | 'gt'
59 | | 'ge'
60 | | 'in'
61 | | 'nin'
62 | | 'subsetof'
63 | | 'anyof'
64 | | 'noneof'
65 | | 'size'
66 | | 'sizeof';
67 | left: OperationContent;
68 | right: OperationContent;
69 | }
70 | | { type: 'comparator'; operator: 'reg'; left: OperationContent; right: ValueRegex }
71 | | { type: 'comparator'; operator: 'empty'; left: OperationContent; right: null };
72 |
73 | export type DotContent = Identifier | NumericLiteral | Wildcard;
74 |
75 | export type Dot = {
76 | type: 'dot';
77 | value: DotContent;
78 | };
79 |
80 | export type DotDotContent = Identifier | Wildcard | BracketMember | BracketExpression;
81 |
82 | export type DotDot = {
83 | type: 'dotdot';
84 | value: DotDotContent;
85 | };
86 |
87 | export type BracketMemberContent = Identifier | NumericLiteral | StringLiteral;
88 | export type BracketExpressionContent = Wildcard | FilterExpression | Slices | Unions | Indexes;
89 |
90 | export type BracketExpression = {
91 | type: 'bracketExpression';
92 | value: BracketExpressionContent;
93 | };
94 |
95 | export type BracketMember = {
96 | type: 'bracketMember';
97 | value: BracketMemberContent;
98 | };
99 |
100 | export type Subscript = {
101 | type: 'subscript';
102 | value: Dot | DotDot | BracketMember | BracketExpression;
103 | next: Subscript | null;
104 | };
105 |
106 | export type Wildcard = {
107 | type: 'wildcard';
108 | };
109 |
110 | export type StringLiteral = {
111 | type: 'stringLiteral';
112 | value: string;
113 | };
114 |
115 | export type Identifier = {
116 | type: 'identifier';
117 | value: string;
118 | };
119 |
120 | export type NumericLiteral = {
121 | type: 'numericLiteral';
122 | value: number;
123 | };
124 |
125 | export type Indexes = {
126 | type: 'indexes';
127 | values: NumericLiteral[];
128 | };
129 |
130 | export type Unions = {
131 | type: 'unions';
132 | values: (StringLiteral | Identifier)[];
133 | };
134 |
135 | export type FilterExpressionContent =
136 | | Comparator
137 | | GroupExpression
138 | | LogicalExpression
139 | | NotExpression
140 | | Current
141 | | Root
142 | | Value;
143 |
144 | export type FilterExpression = {
145 | type: 'filterExpression';
146 | value: FilterExpressionContent;
147 | };
148 |
149 | export type OperationContent = Root | Current | Value | GroupOperation | Operation;
150 |
151 | export type Operation = {
152 | type: 'operation';
153 | operator: 'plus' | 'minus' | 'multi' | 'div' | '';
154 | left: OperationContent;
155 | right: OperationContent;
156 | };
157 |
158 | export type JsonPathElement =
159 | | ValueObject
160 | | ValueString
161 | | ValueBoolean
162 | | ValueArray
163 | | ValueNumber
164 | | ValueNull
165 | | ValueRegex
166 | | Root
167 | | Current
168 | | NotExpression
169 | | GroupOperation
170 | | GroupExpression
171 | | LogicalExpression
172 | | Slices
173 | | Comparator
174 | | Dot
175 | | DotDot
176 | | BracketMember
177 | | BracketExpression
178 | | Subscript
179 | | Wildcard
180 | | StringLiteral
181 | | Identifier
182 | | NumericLiteral
183 | | Indexes
184 | | Unions
185 | | FilterExpression
186 | | Operation;
187 |
--------------------------------------------------------------------------------
/tests/parse.test.ts:
--------------------------------------------------------------------------------
1 | import { parse } from '../src/parser/parse';
2 | import { stringify } from '../src/parser/stringify';
3 | import { expect } from 'chai';
4 |
5 | describe('parse', () => {
6 | const textCases = [
7 | [`$.store.book[?(@.size nin ['M','L'])]`, ''],
8 | [`$.store.book[?(@.size nin ["M","L"])]`, ''],
9 | [`$..book[?(@.author == {"test":1})].title`, ''],
10 | [`$["book"]`, ''],
11 | [`$["book with space"]`, ''],
12 | [`$['book with "double" quotes']`, `$["book with \"double\" quotes"]`],
13 | [`$["book with 'single' quotes"]`, '$["book with \'single\' quotes"]'],
14 | [`$.book["test"].title`, ''],
15 | [`$.phoneNumbers[?(@.price < 30)]`, ''],
16 | [`$.phoneNumbers[?((@.price < 30 && @.type == "iPhone") || @.num == 1)]`, ''],
17 | [`$`, ''],
18 | [`$[*]`, ''],
19 | [`$[0]`, ''],
20 | [`$[?(@.author)]`, ''],
21 | [`$..["book"]`, ''],
22 | [`$..book[0][category, author]`, ''],
23 | [`$..phoneNumbers[?(!(@.price < 30 && !(@.type == "iPhone") && !(@.number)))]`, ''],
24 | [`$..phoneNumbers[?(!(@.price < 30) && !(@.type == "iPhone") && !(@.number))]`, ''],
25 | [`$..phoneNumbers[?(@.price < 30 && !(@.type == "iPhone" && @.number))]`, ''],
26 | [`$.book[test, toto]`, ''],
27 | [`$.book["test", "toto"]`, ''],
28 | [`$.store.book[?(@.price < 10)]`, ''],
29 | [`$.store.book[?(@.price < 8 + 2)]`, ''],
30 | [`$.store.book[?(@.price < 8 * 2)]`, ''],
31 | [`$.store.book[?(@.price < 8 / 2)]`, ''],
32 | [`$.store.book[?(@.price < (8 / 2) + 1)]`, ''],
33 | [`$.store.book[?(@.price < 8 + @.price)]`, ''],
34 | [`$.store.book[?(@.price < 8 - 2)]`, ''],
35 | [`$.store.book[?(@.price == 10.2)]`, ''],
36 | [`$.store.book[?(@.price == true)]`, ''],
37 | [`$.store.book[?(@.price == false)]`, ''],
38 | [`$.store.book[?(@.price == null)]`, ''],
39 | [`$.store.book[?(@.price <= $.expensive)]`, ''],
40 | [`$.store.book[?(@.price == $.expensive)]`, ''],
41 | [`$.store.book[?(@.price != $.expensive)]`, ''],
42 | [`$.store.book[?(@.price >= $.expensive)]`, ''],
43 | [`$.store.book[?(@.price > $.expensive)]`, ''],
44 | [`$.store.book[?(@.price =~ /hello/)]`, ''],
45 | [`$.store.book[?(@.price =~ /hello/i)]`, ''],
46 | [`$.store.book[?(@.price =~ /hello/gui)]`, ''],
47 | [`$.store.book[?(@.price in [1,2,3])]`, ''],
48 | [`$..book[?(@.isbn)]`, ''],
49 | [`$..book[?(!(@.isbn))]`, ''],
50 | [`$..book[-1:].title`, ''],
51 | [`$..book[0, 1].title`, ''],
52 | [`$..book[0:1].title`, ''],
53 | [`$..book[:2].title`, ''],
54 | [`$..book[5:2].title`, ''],
55 | [`$..book[:7:2].title`, ''],
56 | [`$..book[::2].title`, ''],
57 | [`$..book[1::2].title`, ''],
58 | [`$..book[:1:].title`, `$..book[:1].title`],
59 | [`$..book[1::].title`, `$..book[1:].title`],
60 | [`$..book[5::2].title`, ''],
61 | [`$..book[:].title`, ''],
62 | [`$..book[0:2:1].title`, ''],
63 | [`$..book[?(@.author == 'J.R.R. Tolkien')].title`, ''],
64 | [`$..*`, ''],
65 | ];
66 |
67 | textCases.forEach(([input, expected]) => {
68 | it(input, (done) => {
69 | expect(() => {
70 | const tree = parse(input);
71 |
72 | if (expected) {
73 | expect(stringify(tree || null)).to.deep.equal(expected);
74 | } else {
75 | expect(stringify(tree || null)).to.deep.equal(input.replace(/'/g, '"'));
76 | }
77 | done();
78 | }).not.to.throw(Error);
79 | });
80 | });
81 |
82 | it('should not throw exceptions', () => {
83 | const tree = parse('bad', { hideExceptions: true });
84 |
85 | expect(tree).to.be.null;
86 | });
87 | it('should throw exceptions', () => {
88 | expect(() => {
89 | parse('bad');
90 | }).to.throw(Error);
91 | });
92 | });
93 |
--------------------------------------------------------------------------------
/tests/paths.test.ts:
--------------------------------------------------------------------------------
1 | import { paths, PathsOptions } from '../src/handler/paths';
2 | import { query } from '../src/handler/query';
3 | import { expect } from 'chai';
4 |
5 | describe('paths', () => {
6 | const PAYLOAD = {
7 | array: [1, 2, 3, 4, 5, 6, 7, 8, 9],
8 | nested: {
9 | nested: [
10 | {
11 | nested: 2,
12 | exist: true,
13 | },
14 | {
15 | nested: 3,
16 | test: { nested: [] },
17 | },
18 | ],
19 | },
20 | other: {
21 | nested: 5,
22 | object: {
23 | test: '1',
24 | nested: 10,
25 | },
26 | },
27 | };
28 |
29 | const testCases = [
30 | { payload: PAYLOAD, path: `$.string` },
31 | { payload: PAYLOAD, path: `$.array.2` },
32 | { payload: PAYLOAD, path: `$.bad` },
33 | { payload: PAYLOAD, path: `$.array[?(@ > 3)]` },
34 | { payload: PAYLOAD, path: `$.array[?(@ > 3)]` },
35 | { payload: PAYLOAD, path: `$.*.book` },
36 | { payload: PAYLOAD, path: `$..*..book` },
37 | { payload: PAYLOAD, path: `$..*..book[*]` },
38 | { payload: PAYLOAD, path: `$..nested` },
39 | { payload: PAYLOAD, path: `$..*.nested..nested` },
40 | { payload: PAYLOAD, path: `$..*..*[0].nested` },
41 | { payload: PAYLOAD, path: `$..*..*[10].nested` },
42 | { payload: PAYLOAD, path: `$..*..*[10].nested` },
43 | { payload: PAYLOAD, path: `$..nested.nested[*]["nested"]` },
44 | { payload: PAYLOAD, path: `$..*.object` },
45 | { payload: PAYLOAD, path: `$..*.object..test` },
46 | { payload: PAYLOAD, path: `$..*.object.test` },
47 | { payload: PAYLOAD, path: `$.*.object.test` },
48 | { payload: PAYLOAD, path: `$..nested[?(@.number==1)]` },
49 | { payload: PAYLOAD, path: `$..[?(@.number < 2 )]` },
50 | { payload: PAYLOAD, path: `$..nested[?(@.number>=2)]` },
51 | { payload: PAYLOAD, path: `$..nested[?(@.number>=2)].number` },
52 | { payload: PAYLOAD, path: `$..nested[?(@.bad+2>=2)].number` },
53 | { payload: PAYLOAD, path: `$..nested[?(@.exist)]` },
54 | { payload: PAYLOAD, path: `$..nested[0,2]` },
55 | { payload: PAYLOAD, path: `$.array[-1]` },
56 | { payload: PAYLOAD, path: `$.array[10,11,12]` },
57 | { payload: PAYLOAD, path: `$.array[10]` },
58 | { payload: PAYLOAD, path: `$.string[1:3]` },
59 | { payload: PAYLOAD, path: `$.array[1:3]` },
60 | { payload: PAYLOAD, path: `$.array[-1:]` },
61 | { payload: PAYLOAD, path: `$.array[:3]` },
62 | { payload: PAYLOAD, path: `$.array[5:2]` },
63 | { payload: PAYLOAD, path: `$.array[:7:2]` },
64 | { payload: PAYLOAD, path: `$.array[::3]` },
65 | { payload: PAYLOAD, path: `$.array[2::3]` },
66 | { payload: PAYLOAD, path: `$.array[:2:]` },
67 | { payload: PAYLOAD, path: `$.array[:2]` },
68 | { payload: PAYLOAD, path: `$.array[7::]` },
69 | { payload: PAYLOAD, path: `$.array[5::2]` },
70 | { payload: PAYLOAD, path: `$.array[:]` },
71 | { payload: PAYLOAD, path: `$.array[0:2:2]` },
72 | { payload: PAYLOAD, path: `$..nested["value", "exist"]` },
73 | { payload: PAYLOAD, path: `$..*..nested.*` },
74 | ];
75 |
76 | testCases.forEach(({ payload, path }) => {
77 | it(path, () => {
78 | const res1 = query(payload, path, { returnArray: true });
79 | const res2 = paths(payload, path);
80 | const res3 = query(payload, res2 as string[]);
81 |
82 | expect(res1).to.deep.equal(res3);
83 | });
84 | });
85 |
86 | describe('exceptions', () => {
87 | const PAYLOAD = {
88 | string: 'string',
89 | array: [1, 2, 3, 4],
90 | nested: {
91 | object: 1,
92 | },
93 | };
94 | const testCases = [
95 | { payload: PAYLOAD, path: `$.string`, expected: [`$["string"]`], opts: {} },
96 | { payload: PAYLOAD, path: `$.array.2`, expected: [`$["array"][2]`], opts: {} },
97 | { payload: PAYLOAD, path: `$.bad`, expected: [], opts: {} },
98 | { payload: PAYLOAD, path: `$.array[?(@ > 3)]`, expected: [`$["array"][3]`], opts: {} },
99 | { payload: PAYLOAD, path: `$.array["badQUote']`, expected: [], opts: { hideExceptions: true } },
100 | ];
101 |
102 | testCases.forEach(({ payload, path, expected, opts }) => {
103 | it(path, () => {
104 | const res = paths(payload, path, opts as PathsOptions);
105 |
106 | expect(res).to.deep.equal(expected);
107 | });
108 | });
109 |
110 | it('should throw exception', () => {
111 | expect(() => {
112 | paths({}, 'bad');
113 | }).to.throw(Error);
114 | });
115 | });
116 | });
117 |
--------------------------------------------------------------------------------
/tests/query.test.ts:
--------------------------------------------------------------------------------
1 | import { query } from '../src/handler/query';
2 | import { JSONPathSyntaxError } from '../src/parser/errors';
3 | import { expect } from 'chai';
4 |
5 | describe('query', () => {
6 | describe('with dot notations', () => {
7 | const PAYLOAD = {
8 | string: 'string',
9 | array: [1, 2, 3, 4],
10 | nested: {
11 | object: 1,
12 | },
13 | };
14 | const testCases = [
15 | { payload: PAYLOAD, path: `$.string`, expected: PAYLOAD.string },
16 | { payload: PAYLOAD, path: `$.array.2`, expected: PAYLOAD.array[2] },
17 | { payload: PAYLOAD, path: `$.array.10`, expected: undefined },
18 | { payload: PAYLOAD, path: `$.array.-1`, expected: PAYLOAD.array[3] },
19 | { payload: PAYLOAD, path: `$.nested.object`, expected: PAYLOAD.nested.object },
20 | { payload: PAYLOAD, path: `$.*`, expected: Object.values(PAYLOAD) },
21 | { payload: PAYLOAD, path: `$.*.object`, expected: [1] },
22 | { payload: PAYLOAD, path: `$.nested.*`, expected: Object.values(PAYLOAD.nested) },
23 | { payload: PAYLOAD, path: `$.bad`, expected: undefined },
24 | {
25 | payload: {
26 | empty: 'value',
27 | },
28 | path: `$.empty`,
29 | expected: 'value',
30 | },
31 | { payload: [PAYLOAD], path: `$.string`, expected: undefined },
32 | {
33 | payload: {
34 | key: 42,
35 | key_: 43,
36 | _: 44,
37 | dash: 45,
38 | _dash: 46,
39 | '': 47,
40 | // eslint-disable-next-line @typescript-eslint/camelcase
41 | 'key_underscore-toto': 'value',
42 | something: 'else',
43 | },
44 | path: '$.key_underscore-toto',
45 | expected: 'value',
46 | },
47 | ];
48 |
49 | testCases.forEach(({ payload, path, expected }) => {
50 | it(path, () => {
51 | const res = query(payload, path);
52 |
53 | expect(res).to.deep.equal(expected);
54 | });
55 | });
56 | });
57 |
58 | describe('with dot dot notations', () => {
59 | describe('with identifier / stringLiteral / numericLiteral', () => {
60 | const PAYLOAD = {
61 | nested: {
62 | nested: [
63 | {
64 | nested: 2,
65 | exist: true,
66 | },
67 | {
68 | nested: 3,
69 | test: { nested: [] },
70 | },
71 | ],
72 | },
73 | other: {
74 | object: {
75 | test: '1',
76 | },
77 | },
78 | };
79 | const testCases = [
80 | { payload: PAYLOAD, path: `$..notExist`, expected: [] },
81 | {
82 | payload: PAYLOAD,
83 | path: `$..nested..nested..nested`,
84 | expected: [2, 3, []],
85 | },
86 | {
87 | payload: PAYLOAD,
88 | path: `$..other`,
89 | expected: [PAYLOAD.other],
90 | },
91 | {
92 | payload: PAYLOAD,
93 | path: `$..["nested"].nested..test`,
94 | expected: [PAYLOAD.nested.nested[1].test],
95 | },
96 | {
97 | payload: PAYLOAD,
98 | path: `$..nested["nested"]..["test"]`,
99 | expected: [PAYLOAD.nested.nested[1].test],
100 | },
101 | {
102 | payload: PAYLOAD,
103 | path: `$..nested.nested[0]`,
104 | expected: [PAYLOAD.nested.nested[0]],
105 | },
106 | {
107 | payload: PAYLOAD,
108 | path: `$..nested.nested.1`,
109 | expected: [PAYLOAD.nested.nested[1]],
110 | },
111 | {
112 | payload: PAYLOAD,
113 | path: `$..nested.nested.1.test`,
114 | expected: [PAYLOAD.nested.nested[1].test],
115 | },
116 | ];
117 |
118 | testCases.forEach(({ payload, path, expected }) => {
119 | it(path, () => {
120 | const res = query(payload, path);
121 |
122 | expect(res).to.deep.equal(expected);
123 | });
124 | });
125 | });
126 |
127 | describe('with wildcard', () => {
128 | const PAYLOAD = {
129 | nested: {
130 | nested: [
131 | {
132 | nested: 2,
133 | exist: true,
134 | },
135 | {
136 | nested: 3,
137 | test: { nested: [] },
138 | },
139 | ],
140 | },
141 | other: {
142 | object: {
143 | test: '1',
144 | },
145 | },
146 | };
147 | const testCases = [
148 | { payload: { store: { book: [1, 2, 3] } }, path: `$.*.book`, expected: [[1, 2, 3]] },
149 | { payload: { store: { book: [1, 2, 3] } }, path: `$..*..book`, expected: [[1, 2, 3]] },
150 | { payload: { store: { book: [1, 2, 3] } }, path: `$..*..book[*]`, expected: [1, 2, 3] },
151 | { payload: PAYLOAD, path: `$..*.nested..nested`, expected: [2, 3, []] },
152 | { payload: PAYLOAD, path: `$..[*].nested..["nested"]`, expected: [2, 3, []] },
153 | { payload: PAYLOAD, path: `$..*..*[0].nested`, expected: [2] },
154 | { payload: PAYLOAD, path: `$..*..[*][0].nested`, expected: [2] },
155 | { payload: PAYLOAD, path: `$..*..*[10].nested`, expected: [] },
156 | { payload: PAYLOAD, path: `$..nested.nested[*]["nested", "exist"]`, expected: [2, true, 3] },
157 | { payload: [PAYLOAD], path: `$..nested.nested[*]["nested", "exist"]`, expected: [2, true, 3] },
158 | { payload: PAYLOAD, path: `$..*.object`, expected: [{ test: '1' }] },
159 | { payload: PAYLOAD, path: `$..*..*..*..*..*`, expected: [[]] },
160 | { payload: PAYLOAD, path: `$..*..*..*..*..[*]`, expected: [[]] },
161 | { payload: PAYLOAD, path: `$..*.object..test`, expected: ['1'] },
162 | { payload: PAYLOAD, path: `$..*.object.test`, expected: ['1'] },
163 | { payload: [PAYLOAD], path: `$..*.object.test`, expected: ['1'] },
164 | ];
165 |
166 | testCases.forEach(({ payload, path, expected }) => {
167 | it(path, () => {
168 | const res = query(payload, path);
169 |
170 | expect(res).to.deep.equal(expected);
171 | });
172 | });
173 | });
174 |
175 | describe('with filters', () => {
176 | const PAYLOAD = {
177 | number: 2,
178 | nested: {
179 | nested: [{ number: 1, exist: true }, { number: 2 }, { number: 3 }],
180 | },
181 | };
182 |
183 | const testCases = [
184 | { payload: PAYLOAD, path: `$..nested.*["number", "exist"]`, expected: [1, true, 2, 3] },
185 | {
186 | payload: PAYLOAD,
187 | path: `$..nested[?(@.number==1)]`,
188 | expected: [PAYLOAD.nested.nested[0]],
189 | },
190 | {
191 | payload: [PAYLOAD],
192 | path: `$..nested[?(@.number==1)]`,
193 | expected: [PAYLOAD.nested.nested[0]],
194 | },
195 | {
196 | payload: { number: 1, exist: true },
197 | path: `$..[?(@.number==1)]`,
198 | expected: [{ number: 1, exist: true }],
199 | },
200 | {
201 | payload: [{ number: 1, exist: true }],
202 | path: `$..[?(@.number==1)]`,
203 | expected: [{ number: 1, exist: true }],
204 | },
205 | {
206 | payload: PAYLOAD,
207 | path: `$..[?(@.number < 2 )]`,
208 | expected: [{ number: 1, exist: true }],
209 | },
210 | {
211 | payload: PAYLOAD,
212 | path: `$..nested[?(@.number>=2)]`,
213 | expected: [PAYLOAD.nested.nested[1], PAYLOAD.nested.nested[2]],
214 | },
215 | {
216 | payload: PAYLOAD,
217 | path: `$..nested[?(@.number>=2)].number`,
218 | expected: [2, 3],
219 | },
220 | {
221 | payload: PAYLOAD,
222 | path: `$..nested[?(@.exist)]`,
223 | expected: [PAYLOAD.nested.nested[0]],
224 | },
225 | {
226 | payload: PAYLOAD,
227 | path: `$..nested[?(@.number < $.number)]`,
228 | expected: [PAYLOAD.nested.nested[0]],
229 | },
230 | {
231 | payload: PAYLOAD,
232 | path: `$..nested[0,2]`,
233 | expected: [PAYLOAD.nested.nested[0], PAYLOAD.nested.nested[2]],
234 | },
235 | {
236 | payload: PAYLOAD,
237 | path: `$..nested[:2]`,
238 | expected: [PAYLOAD.nested.nested[0], PAYLOAD.nested.nested[1]],
239 | },
240 | ];
241 |
242 | testCases.forEach(({ payload, path, expected }) => {
243 | it(path, () => {
244 | const res = query(payload, path);
245 |
246 | expect(res).to.deep.equal(expected);
247 | });
248 | });
249 | });
250 | });
251 |
252 | describe('with bracket numeric value', () => {
253 | const PAYLOAD = {
254 | string: 'stringValue',
255 | number: 0,
256 | arrayOfNumber: [1, 2, 3, 4, 5, 6, 7, 8, 9],
257 | };
258 |
259 | const testCases = [
260 | { payload: PAYLOAD, path: `$.arrayOfNumber[-1]`, expected: 9 },
261 | { payload: PAYLOAD, path: `$.arrayOfNumber[1]`, expected: 2 },
262 | { payload: PAYLOAD, path: `$.arrayOfNumber[1,3,5]`, expected: [2, 4, 6] },
263 | { payload: PAYLOAD, path: `$.arrayOfNumber[10,11,12]`, expected: [] },
264 | { payload: PAYLOAD, path: `$.arrayOfNumber[10,1,12]`, expected: [2] },
265 | { payload: PAYLOAD, path: `$.arrayOfNumber[10]`, expected: undefined },
266 | { payload: PAYLOAD, path: `$.string[0]`, expected: undefined },
267 | { payload: PAYLOAD, path: `$.string[0,1,2]`, expected: [] },
268 | { payload: PAYLOAD, path: `$.number[0]`, expected: undefined },
269 | { payload: PAYLOAD, path: `$.number.0`, expected: undefined },
270 | ];
271 |
272 | testCases.forEach(({ payload, path, expected }) => {
273 | it(path, () => {
274 | const res = query(payload, path);
275 |
276 | expect(res).to.deep.equal(expected);
277 | });
278 | });
279 | });
280 |
281 | describe('with bracket string value', () => {
282 | const PAYLOAD = {
283 | string: 'stringValue',
284 | number: 0,
285 | arrayOfNumber: [1, 2, 3, 4, 5, 6, 7, 8, 9],
286 | arrayOfString: ['11', '22', '33', '44', '55'],
287 | nestedObject: {
288 | object: {
289 | test: '1',
290 | },
291 | },
292 | };
293 |
294 | const testCases = [
295 | { payload: PAYLOAD, path: `$["notExist"]`, undefined },
296 | { payload: PAYLOAD, path: `$["string"]`, expected: PAYLOAD.string },
297 | // Different implementation depending on libraries
298 | { payload: PAYLOAD, path: `$[string, number]`, expected: [PAYLOAD.string, PAYLOAD.number] },
299 | { payload: PAYLOAD, path: `$["string", "number"]`, expected: [PAYLOAD.string, PAYLOAD.number] },
300 | { payload: PAYLOAD, path: `$["nestedObject"]["object"]`, expected: PAYLOAD.nestedObject.object },
301 | { payload: PAYLOAD, path: `$[nestedObject]`, expected: PAYLOAD.nestedObject },
302 | { payload: PAYLOAD, path: `$[*]`, expected: Object.values(PAYLOAD) },
303 | { payload: PAYLOAD, path: `$[*]["object"]`, expected: [PAYLOAD.nestedObject.object] },
304 | ];
305 |
306 | testCases.forEach(({ payload, path, expected }) => {
307 | it(path, () => {
308 | const res = query(payload, path);
309 |
310 | expect(res).to.deep.equal(expected);
311 | });
312 | });
313 | });
314 |
315 | describe('with array slice', () => {
316 | const PAYLOAD = {
317 | string: 'stringValue',
318 | arrayOfNumber: [1, 2, 3, 4, 5, 6, 7, 8, 9],
319 | };
320 |
321 | const testCases = [
322 | { payload: PAYLOAD, path: `$.string[1:3]`, expected: [] },
323 | { payload: PAYLOAD, path: `$.arrayOfNumber[1:3]`, expected: [2, 3] },
324 | { payload: PAYLOAD, path: `$.arrayOfNumber[-1:]`, expected: [9] },
325 | { payload: PAYLOAD, path: `$.arrayOfNumber[:3]`, expected: [1, 2, 3] },
326 | { payload: PAYLOAD, path: `$.arrayOfNumber[5:2]`, expected: [] },
327 | { payload: PAYLOAD, path: `$.arrayOfNumber[:7:2]`, expected: [1, 3, 5, 7] },
328 | { payload: PAYLOAD, path: `$.arrayOfNumber[::3]`, expected: [1, 4, 7] },
329 | { payload: PAYLOAD, path: `$.arrayOfNumber[2::3]`, expected: [3, 6, 9] },
330 | { payload: PAYLOAD, path: `$.arrayOfNumber[:2:]`, expected: [1, 2] },
331 | { payload: PAYLOAD, path: `$.arrayOfNumber[:2]`, expected: [1, 2] },
332 | { payload: PAYLOAD, path: `$.arrayOfNumber[7::]`, expected: [8, 9] },
333 | { payload: PAYLOAD, path: `$.arrayOfNumber[5::2]`, expected: [6, 8] },
334 | { payload: PAYLOAD, path: `$.arrayOfNumber[:]`, expected: PAYLOAD.arrayOfNumber },
335 | { payload: PAYLOAD, path: `$.arrayOfNumber[0:2:2]`, expected: [1] },
336 | ];
337 |
338 | testCases.forEach(({ payload, path, expected }) => {
339 | it(path, () => {
340 | const res = query(payload, path);
341 |
342 | expect(res).to.deep.equal(expected);
343 | });
344 | });
345 | });
346 |
347 | describe('with comparators', () => {
348 | const PAYLOAD = {
349 | arrayOfNumber: [1, 2, 3, 4, 5, 6, 7, 8, 9],
350 | arraySimpleObjects: [
351 | { number: 2, string: 'ABC', exist: true, array: [1, 2, 3], str: '123' },
352 | { number: 5, string: 'BCD', array: [4, 5, 6], str: '' },
353 | { number: 7, string: 'CDE', array: [4, 5, 6], arr: [] },
354 | ],
355 | };
356 |
357 | const testCases = [
358 | {
359 | path: `$.arraySimpleObjects[?(@.number=="2")]..number`,
360 | expected: [],
361 | },
362 | {
363 | path: `$.arraySimpleObjects[?(@.number*2==@.number+@.number)]..number`,
364 | expected: [2, 5, 7],
365 | },
366 | {
367 | path: `$.arraySimpleObjects[?(@.number*2==@.number+@.number)]..["number"]`,
368 | expected: [2, 5, 7],
369 | },
370 | {
371 | path: `$.arraySimpleObjects[?(@)]..number`,
372 | expected: [2, 5, 7],
373 | },
374 | {
375 | path: `$.arraySimpleObjects[?($)]..number`,
376 | expected: [2, 5, 7],
377 | },
378 | {
379 | path: `$.arraySimpleObjects[?(@.number>="5")].number`,
380 | expected: [],
381 | },
382 | {
383 | path: `$.arraySimpleObjects[?(@.number>"5")].number`,
384 | expected: [],
385 | },
386 | {
387 | path: `$.arraySimpleObjects[?(@.number<="5")].number`,
388 | expected: [],
389 | },
390 | {
391 | path: `$.arraySimpleObjects[?(@.number<"5")].number`,
392 | expected: [],
393 | },
394 | {
395 | path: `$.arraySimpleObjects[?(@.number in "5")].number`,
396 | expected: [],
397 | },
398 | {
399 | path: `$.arraySimpleObjects[?(@.number nin "5")].number`,
400 | expected: [],
401 | },
402 | {
403 | path: `$[?([1,2,3] subsetof @.arrayOfNumber)]`,
404 | expected: [PAYLOAD],
405 | },
406 | {
407 | path: `$[?([10,3,3] subsetof @.arrayOfNumber)]`,
408 | expected: [],
409 | },
410 | {
411 | path: `$[?(123 subsetof @.arrayOfNumber)]`,
412 | expected: [],
413 | },
414 | {
415 | path: `$[?([10,11,2] anyof @.arrayOfNumber)]`,
416 | expected: [PAYLOAD],
417 | },
418 | {
419 | path: `$[?([10,11,12] anyof @.arrayOfNumber)]`,
420 | expected: [],
421 | },
422 | {
423 | path: `$[?(123 anyof @.arrayOfNumber)]`,
424 | expected: [],
425 | },
426 | {
427 | path: `$[?([10,11,12] noneof @.arrayOfNumber)]`,
428 | expected: [PAYLOAD],
429 | },
430 | {
431 | path: `$[?([10,11,1] noneof @.arrayOfNumber)]`,
432 | expected: [],
433 | },
434 | {
435 | path: `$[?(123 noneof @.arrayOfNumber)]`,
436 | expected: [],
437 | },
438 | {
439 | path: `$[?(@.arrayOfNumber sizeof @.arrayOfNumber)]`,
440 | expected: [PAYLOAD],
441 | },
442 | {
443 | path: `$[?(@.arrayOfNumber sizeof 123)]`,
444 | expected: [],
445 | },
446 | {
447 | path: `$[?(@.arrayOfNumber empty)]`,
448 | expected: [],
449 | },
450 | {
451 | path: `$.arraySimpleObjects[?(@.arr empty)]`,
452 | expected: [PAYLOAD.arraySimpleObjects[2]],
453 | },
454 | {
455 | path: `$.arraySimpleObjects[?(@.str empty)]`,
456 | expected: [PAYLOAD.arraySimpleObjects[1]],
457 | },
458 | {
459 | path: `$[?(123 sizeof @.arrayOfNumber)]`,
460 | expected: [],
461 | },
462 | {
463 | path: `$[?([1,2,3,4,5,6,7,8,9,10] sizeof @.arrayOfNumber)]`,
464 | expected: [],
465 | },
466 | {
467 | path: `$[?(@.arrayOfNumber size 9)]`,
468 | expected: [PAYLOAD],
469 | },
470 | {
471 | path: `$[?(@.arrayOfNumber size "9")]`,
472 | expected: [],
473 | },
474 | {
475 | path: `$[?(123 size 9)]`,
476 | expected: [],
477 | },
478 | {
479 | path: `$[?(@.arrayOfNumber size 8)]`,
480 | expected: [],
481 | },
482 | {
483 | path: `$[?(123 sizeof 9)]`,
484 | expected: [],
485 | },
486 | {
487 | path: `$.arraySimpleObjects[?(@.number==2)].number`,
488 | expected: [2],
489 | },
490 | {
491 | path: `$.arraySimpleObjects[?(@.number!=2)].number`,
492 | expected: [5, 7],
493 | },
494 | {
495 | path: `$.arraySimpleObjects[?(@.number==2)]..number`,
496 | expected: [2],
497 | },
498 | {
499 | path: `$.arraySimpleObjects[?(@.exist)].number`,
500 | expected: [2],
501 | },
502 | {
503 | path: `$.arraySimpleObjects[?(@.number>=5)].number`,
504 | expected: [5, 7],
505 | },
506 | {
507 | path: `$.arraySimpleObjects[?(@.number>5)].number`,
508 | expected: [7],
509 | },
510 | {
511 | path: `$.arraySimpleObjects[?(@.number<=5)].number`,
512 | expected: [2, 5],
513 | },
514 | {
515 | path: `$.arraySimpleObjects[?(@.number<5)].number`,
516 | expected: [2],
517 | },
518 | {
519 | path: `$.arraySimpleObjects[?(@.number in [1,2])].number`,
520 | expected: [2],
521 | },
522 | {
523 | path: `$.arraySimpleObjects[?(@.number nin [1,2])].number`,
524 | expected: [5, 7],
525 | },
526 | {
527 | path: `$.arraySimpleObjects[?(1 in @.array)].number`,
528 | expected: [2],
529 | },
530 | ];
531 |
532 | testCases.forEach(({ path, expected }) => {
533 | it(path, () => {
534 | const res = query(PAYLOAD, path);
535 |
536 | expect(res).to.deep.equal(expected);
537 | });
538 | });
539 | });
540 |
541 | describe('with comparator operations', () => {
542 | const PAYLOAD = {
543 | number: 0,
544 | arraySimpleObjects: [
545 | { number: 2, string: 'ABC', exist: true, array: [1, 2, 3] },
546 | { number: 5, string: 'BCD', array: [4, 5, 6] },
547 | { number: 7, string: 'CDE', array: [4, 5, 6] },
548 | ],
549 | };
550 |
551 | const testCases = [
552 | {
553 | path: `$.arraySimpleObjects[?(@.number>$.number+3)]..number`,
554 | expected: [5, 7],
555 | },
556 | {
557 | path: `$.arraySimpleObjects[?(@.number>$['number']+3)]..number`,
558 | expected: [5, 7],
559 | },
560 | {
561 | path: `$.arraySimpleObjects[?(@.number>$.number+6)]..number`,
562 | expected: [7],
563 | },
564 | {
565 | path: `$.arraySimpleObjects[?(@.number>$.number+7-10/10)]..number`,
566 | expected: [7],
567 | },
568 | {
569 | path: `$.arraySimpleObjects[?(@.number>$.number+7-10/0)]..number`,
570 | expected: [],
571 | },
572 | {
573 | path: `$.arraySimpleObjects[?(@.number>$.number+2+2*2)]..number`,
574 | expected: [7],
575 | },
576 | {
577 | path: `$.arraySimpleObjects[?(@.number>$.number+(2+2)*2)]..number`,
578 | expected: [],
579 | },
580 | {
581 | path: `$.arraySimpleObjects[?(@.number + 2 >$.number + 8)]..number`,
582 | expected: [7],
583 | },
584 | {
585 | path: `$.arraySimpleObjects[?(@.number>3+10-8+1)]..number`,
586 | expected: [7],
587 | },
588 | {
589 | path: `$.arraySimpleObjects[?(@.number>3 + 10 - 8 + 1)]..number`,
590 | expected: [7],
591 | },
592 | {
593 | path: `$.arraySimpleObjects[?(@.number - 1 > @.number)]..number`,
594 | expected: [],
595 | },
596 | {
597 | path: `$.arraySimpleObjects[?(@.number + 1 > @.number)]..number`,
598 | expected: [2, 5, 7],
599 | },
600 | ];
601 |
602 | testCases.forEach(({ path, expected }) => {
603 | const res = query(PAYLOAD, path);
604 |
605 | expect(res).to.deep.equal(expected);
606 | });
607 |
608 | it('should throw exception on missing operator', () => {
609 | expect(() => {
610 | query(PAYLOAD, '$.arraySimpleObjects[?(@.number>3 4)]..number');
611 | }).to.throw(Error);
612 | });
613 | });
614 |
615 | describe('with bad path', () => {
616 | const testCases = [
617 | { path: 'bad', err: JSONPathSyntaxError },
618 | { path: '', err: JSONPathSyntaxError },
619 | { path: '$...bad', err: JSONPathSyntaxError },
620 | { path: '$.$', err: JSONPathSyntaxError },
621 | { path: `$["bad Quote']`, err: JSONPathSyntaxError },
622 | { path: `$[bad Quote']`, err: JSONPathSyntaxError },
623 | { path: `$\{bad\}`, err: JSONPathSyntaxError },
624 | { path: `@`, err: JSONPathSyntaxError },
625 | { path: `$[?(@.test == {'1': undefined})]`, err: JSONPathSyntaxError },
626 | { path: `$[1:2:3:4]`, err: JSONPathSyntaxError },
627 | { path: `$[[1:2:3]]`, err: JSONPathSyntaxError },
628 | ];
629 |
630 | testCases.forEach(({ path, err }) => {
631 | expect(() => {
632 | query({ test: 1 }, path);
633 | }).to.throw(err);
634 | });
635 | });
636 |
637 | describe('with logical expressions', () => {
638 | const PAYLOAD = {
639 | number: 0,
640 | arraySimpleObjects: [
641 | { number: 2, string: 'ABC', exist: true, array: [1, 2, 3] },
642 | { number: 5, string: 'BCD', array: [4, 5, 6] },
643 | { number: 7, string: 'CDE', array: [4, 5, 6] },
644 | ],
645 | };
646 |
647 | const testCases = [
648 | {
649 | path: `$.arraySimpleObjects[?(@.number==2 || @.number==7)].number`,
650 | expected: [2, 7],
651 | },
652 | {
653 | path: `$.arraySimpleObjects[?(4 in @.array && @.string=="BCD")].number`,
654 | expected: [5],
655 | },
656 | {
657 | path: `$.arraySimpleObjects[?( (4 in @.array && @.string=="BCD") || @.number==2 )].number`,
658 | expected: [2, 5],
659 | },
660 | {
661 | path: `$.arraySimpleObjects[?( !((4 in @.array && @.string=="BCD") || @.number==2) )].number`,
662 | expected: [7],
663 | },
664 | {
665 | path: `$.arraySimpleObjects[?( $.number==0 )].number`,
666 | expected: [2, 5, 7],
667 | },
668 | {
669 | path: `$.arraySimpleObjects[?($.number)].number`,
670 | expected: [2, 5, 7],
671 | },
672 | ];
673 |
674 | testCases.forEach(({ path, expected }) => {
675 | it(path, () => {
676 | const res = query(PAYLOAD, path);
677 |
678 | expect(res).to.deep.equal(expected);
679 | });
680 | });
681 | });
682 |
683 | describe('with return array option', () => {
684 | const PAYLOAD = {
685 | string: 'stringValue',
686 | number: 0,
687 | arrayOfNumber: [1, 2, 3, 4, 5, 6, 7, 8, 9],
688 | };
689 |
690 | const testCases = [
691 | {
692 | path: `$.number`,
693 | expected: [PAYLOAD.number],
694 | },
695 | {
696 | path: `$.*`,
697 | expected: Object.values(PAYLOAD),
698 | },
699 | {
700 | path: `$.string`,
701 | expected: [PAYLOAD.string],
702 | },
703 | {
704 | path: `$.notExist`,
705 | expected: [],
706 | },
707 | ];
708 |
709 | testCases.forEach(({ path, expected }) => {
710 | it(path, () => {
711 | const res = query(PAYLOAD, path, { returnArray: true });
712 |
713 | expect(res).to.deep.equal(expected);
714 | });
715 | });
716 | });
717 |
718 | describe('with regexp operator', () => {
719 | const REG_PAYLOAD = ['Hello World !', 'hello Earth !', 'Good Morning'];
720 | const testCases = [
721 | { payload: REG_PAYLOAD, path: `$[?(@ =~ /hello/i )]`, expected: [REG_PAYLOAD[0], REG_PAYLOAD[1]] },
722 | { payload: REG_PAYLOAD, path: `$[?(@ =~ /World/g )]`, expected: [REG_PAYLOAD[0]] },
723 | { payload: REG_PAYLOAD, path: `$[?(@ =~ /bad/g )]`, expected: [] },
724 | { payload: REG_PAYLOAD, path: `$[?(@ =~ /.*/g )]`, expected: REG_PAYLOAD },
725 | { payload: [1], path: `$[?(@ =~ /.*/g )]`, expected: [] },
726 | ];
727 |
728 | testCases.forEach(({ payload, path, expected }) => {
729 | it(path, () => {
730 | const res = query(payload, path);
731 |
732 | expect(res).to.deep.equal(expected);
733 | });
734 | });
735 | });
736 |
737 | describe('with hide exception option', () => {
738 | const testCases = [
739 | { path: '$.bad', expected: [], options: { returnArray: true, hideExceptions: true } },
740 | { path: 'bad', expected: [], options: { returnArray: true, hideExceptions: true } },
741 | { path: 'bad', expected: undefined, options: { hideExceptions: true } },
742 | { path: '', expected: undefined, options: { hideExceptions: true } },
743 | { path: '$...bad', expected: undefined, options: { hideExceptions: true } },
744 | { path: '$.$', expected: undefined, options: { hideExceptions: true } },
745 | { path: `$["bad Quote']`, expected: undefined, options: { hideExceptions: true } },
746 | { path: `$[bad Quote']`, expected: undefined, options: { hideExceptions: true } },
747 | { path: `$\{bad\}`, expected: undefined, options: { hideExceptions: true } },
748 | { path: `@`, expected: undefined, options: { hideExceptions: true } },
749 | {
750 | path: `$[?(@.test == {'1': { hideExceptions: true }})]`,
751 | expected: undefined,
752 | options: { hideExceptions: true },
753 | },
754 | { path: `$[1:2:3:4]`, expected: undefined, options: { hideExceptions: true } },
755 | { path: `$[[1:2:3]]`, expected: undefined, options: { hideExceptions: true } },
756 | ];
757 |
758 | testCases.forEach(({ path, expected, options }) => {
759 | it(path, () => {
760 | const res = query({ test: 1 }, path, options);
761 |
762 | expect(res).to.deep.equal(expected);
763 | });
764 | });
765 | });
766 | });
767 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "forceConsistentCasingInFileNames": true,
4 | "target": "es6",
5 | "rootDir": "./src",
6 | "noImplicitAny": true,
7 | "outDir": "./dist",
8 | "moduleResolution": "node",
9 | "strict": true,
10 | "allowJs": true,
11 | "allowSyntheticDefaultImports": true,
12 | "declaration": true,
13 | "types": ["node", "mocha"],
14 | "typeRoots": ["./src/types", "./node_modules/@types"]
15 | },
16 | "include": ["src"],
17 | "exclude": ["node_modules"]
18 | }
19 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-var-requires */
2 | const path = require('path');
3 |
4 | // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
5 | const buildConfig = (platform, extensions) => ({
6 | mode: 'production',
7 | entry: './src/index.ts',
8 | output: {
9 | path: path.resolve(__dirname, 'dist'),
10 | filename: `index.${platform}.${extensions}`,
11 | chunkFormat: extensions === 'mjs' ? 'module' : 'commonjs',
12 | library: {
13 | type: extensions === 'mjs' ? 'module' : 'commonjs',
14 | },
15 | },
16 | module: {
17 | rules: [
18 | {
19 | test: /\.tsx?$/,
20 | use: 'ts-loader',
21 | exclude: /node_modules/,
22 | },
23 | ],
24 | },
25 | resolve: {
26 | extensions: ['.ts', '.js'],
27 | },
28 | externals: ["antlr4"],
29 | target: platform,
30 | plugins: [],
31 | devtool: 'source-map',
32 | experiments: {
33 | outputModule: extensions === 'mjs',
34 | },
35 | });
36 |
37 | module.exports = [
38 | buildConfig('node', 'cjs'),
39 | buildConfig('node', 'mjs'),
40 | buildConfig('web', 'cjs'),
41 | buildConfig('web', 'mjs'),
42 | ];
43 |
--------------------------------------------------------------------------------