├── .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 | [![npm version](https://badge.fury.io/js/jsonpathly.svg)](https://badge.fury.io/js/jsonpathly) 6 | [![codecov](https://codecov.io/gh/atamano/jsonpathly/branch/master/graph/badge.svg?token=QSSZGZMULF)](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 | --------------------------------------------------------------------------------