@swaggerexpert/jsonpath 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -34,6 +34,7 @@ The development of this library contributed to the identification and formal sub
34
34
  - [Installation](#installation)
35
35
  - [Usage](#usage)
36
36
  - [Parsing](#parsing)
37
+ - [Normalized paths](#normalized-paths)
37
38
  - [Translators](#translators)
38
39
  - [CST](#cst-translator)
39
40
  - [XML](#xml-translator)
@@ -70,14 +71,6 @@ import { parse } from '@swaggerexpert/jsonpath';
70
71
  const parseResult = parse('$.store.book[0].title');
71
72
  ```
72
73
 
73
- or
74
-
75
- ```js
76
- import { parse, CSTTranslator } from '@swaggerexpert/jsonpath';
77
-
78
- const parseResult = parse('$.store.book[0].title', { translator: new CSTTranslator() });
79
- ```
80
-
81
74
  **parseResult** variable has the following shape:
82
75
 
83
76
  ```
@@ -91,6 +84,31 @@ const parseResult = parse('$.store.book[0].title', { translator: new CSTTranslat
91
84
 
92
85
  [TypeScript typings](https://github.com/swaggerexpert/jsonpath/blob/main/types/index.d.ts) are available for all fields attached to parse result object returned by the `parse` function.
93
86
 
87
+
88
+ ##### Normalized paths
89
+
90
+ [comment]: <> (SPDX-FileCopyrightText: Copyright &#40;c&#41; 2024 IETF Trust and the persons identified as the document authors. All rights reserved.)
91
+ [comment]: <> (SPDX-License-Identifier: BSD-3-Clause)
92
+
93
+ [Normalized Path](https://www.rfc-editor.org/rfc/rfc9535#name-normalized-paths) is a JSONPath query with restricted syntax.
94
+ A Normalized Path represents the identity of a node in a specific value.
95
+ There is precisely one Normalized Path identifying any particular node in a value.
96
+ Normalized Paths provide a predictable format that simplifies testing and post-processing of nodelists, e.g., to remove duplicate nodes.
97
+ Normalized Paths use the canonical bracket notation, rather than dot notation.
98
+ Single quotes are used in Normalized Paths to delimit string member names. This reduces the number of characters that need escaping when Normalized Paths appear in strings delimited by double quotes.
99
+
100
+ Parsing in normalized path mode can be enabled by setting `normalized` option to `true`.
101
+
102
+ ```js
103
+ import { parse } from '@swaggerexpert/jsonpath';
104
+
105
+ parse("$['a']", { normalized: true });
106
+ parse("$[1]", { normalized: true });
107
+ parse("$[2]", { normalized: true });
108
+ parse("$['a']['b'][1]", { normalized: true });
109
+ parse("$['\\u000b']", { normalized: true });
110
+ ```
111
+
94
112
  ##### Translators
95
113
 
96
114
  `@swaggerexpert/jsonpath` provides several translators to convert the parse result into different tree representations.
package/cjs/grammar.cjs CHANGED
@@ -16,9 +16,9 @@ function grammar() {
16
16
  // ALT = 41
17
17
  // CAT = 60
18
18
  // REP = 32
19
- // RNM = 174
20
- // TLS = 66
21
- // TBS = 30
19
+ // RNM = 178
20
+ // TLS = 64
21
+ // TBS = 28
22
22
  // TRG = 20
23
23
  // --- SABNF superset opcodes
24
24
  // UDT = 0
@@ -2247,17 +2247,17 @@ function grammar() {
2247
2247
  children: [1, 2, 3]
2248
2248
  }; // CAT
2249
2249
  this.rules[69].opcodes[1] = {
2250
- type: 7,
2251
- string: [91]
2252
- }; // TLS
2250
+ type: 4,
2251
+ index: 80
2252
+ }; // RNM(left-bracket)
2253
2253
  this.rules[69].opcodes[2] = {
2254
2254
  type: 4,
2255
2255
  index: 70
2256
2256
  }; // RNM(normal-selector)
2257
2257
  this.rules[69].opcodes[3] = {
2258
- type: 7,
2259
- string: [93]
2260
- }; // TLS
2258
+ type: 4,
2259
+ index: 81
2260
+ }; // RNM(right-bracket)
2261
2261
 
2262
2262
  /* normal-selector */
2263
2263
  this.rules[70].opcodes = [];
@@ -2281,9 +2281,9 @@ function grammar() {
2281
2281
  children: [1, 2, 4]
2282
2282
  }; // CAT
2283
2283
  this.rules[71].opcodes[1] = {
2284
- type: 6,
2285
- string: [39]
2286
- }; // TBS
2284
+ type: 4,
2285
+ index: 87
2286
+ }; // RNM(squote)
2287
2287
  this.rules[71].opcodes[2] = {
2288
2288
  type: 3,
2289
2289
  min: 0,
@@ -2294,9 +2294,9 @@ function grammar() {
2294
2294
  index: 72
2295
2295
  }; // RNM(normal-single-quoted)
2296
2296
  this.rules[71].opcodes[4] = {
2297
- type: 6,
2298
- string: [39]
2299
- }; // TBS
2297
+ type: 4,
2298
+ index: 87
2299
+ }; // RNM(squote)
2300
2300
 
2301
2301
  /* normal-single-quoted */
2302
2302
  this.rules[72].opcodes = [];
@@ -2784,9 +2784,9 @@ function grammar() {
2784
2784
  str += "\n";
2785
2785
  str += "; https://www.rfc-editor.org/rfc/rfc9535#name-normalized-paths\n";
2786
2786
  str += "normalized-path = root-identifier *(normal-index-segment)\n";
2787
- str += "normal-index-segment = \"[\" normal-selector \"]\"\n";
2787
+ str += "normal-index-segment = left-bracket normal-selector right-bracket ; MODIFICATION: surrogate text rule used\n";
2788
2788
  str += "normal-selector = normal-name-selector / normal-index-selector\n";
2789
- str += "normal-name-selector = %x27 *normal-single-quoted %x27 ; 'string'\n";
2789
+ str += "normal-name-selector = squote *normal-single-quoted squote ; 'string', MODIFICATION: surrogate text rule used\n";
2790
2790
  str += "normal-single-quoted = normal-unescaped /\n";
2791
2791
  str += " ESC normal-escapable\n";
2792
2792
  str += "normal-unescaped = ; omit %x0-1F control codes\n";
@@ -9,9 +9,11 @@ var _JSONPathParseError = _interopRequireDefault(require("../errors/JSONPathPars
9
9
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
10
  const grammar = new _grammar.default();
11
11
  const parse = (jsonPath, {
12
- translator = new _CSTTranslator.default(),
12
+ normalized = false,
13
13
  stats = false,
14
- trace = false
14
+ trace = false,
15
+ translator = new _CSTTranslator.default(),
16
+ test = 3
15
17
  } = {}) => {
16
18
  if (typeof jsonPath !== 'string') {
17
19
  throw new TypeError('JSONPath must be a string');
@@ -22,7 +24,8 @@ const parse = (jsonPath, {
22
24
  if (translator) parser.ast = translator;
23
25
  if (stats) parser.stats = new _apgLite.Stats();
24
26
  if (trace) parser.trace = new _apgLite.Trace();
25
- const result = parser.parse(grammar, 'jsonpath-query', jsonPath);
27
+ const startRule = normalized ? 'normalized-path' : 'jsonpath-query';
28
+ const result = parser.parse(grammar, startRule, jsonPath);
26
29
  return {
27
30
  result,
28
31
  tree: (_parser$ast = parser.ast) == null ? void 0 : _parser$ast.getTree(),
@@ -82,6 +82,14 @@ class CSTTranslator extends _apgLite.Ast {
82
82
  // https://www.rfc-editor.org/rfc/rfc9535#section-2.5.2.1
83
83
  this.callbacks['descendant-segment'] = (0, _cst.default)('descendant-segment');
84
84
 
85
+ // https://www.rfc-editor.org/rfc/rfc9535#name-normalized-paths
86
+ this.callbacks['normalized-path'] = (0, _cst.default)('normalized-path');
87
+ this.callbacks['normal-index-segment'] = (0, _cst.default)('normal-index-segment');
88
+ this.callbacks['normal-selector'] = (0, _cst.default)('normal-selector');
89
+ this.callbacks['normal-name-selector'] = (0, _cst.default)('normal-name-selector');
90
+ this.callbacks['normal-index-selector'] = (0, _cst.default)('normal-index-selector');
91
+ this.callbacks['normal-single-quoted'] = (0, _cst.default)('normal-single-quoted');
92
+
85
93
  // Surrogate named rules
86
94
  this.callbacks['dot-prefix'] = (0, _cst.default)('text');
87
95
  this.callbacks['double-dot-prefix'] = (0, _cst.default)('text');
package/es/grammar.mjs CHANGED
@@ -12,9 +12,9 @@ export default function grammar() {
12
12
  // ALT = 41
13
13
  // CAT = 60
14
14
  // REP = 32
15
- // RNM = 174
16
- // TLS = 66
17
- // TBS = 30
15
+ // RNM = 178
16
+ // TLS = 64
17
+ // TBS = 28
18
18
  // TRG = 20
19
19
  // --- SABNF superset opcodes
20
20
  // UDT = 0
@@ -2243,17 +2243,17 @@ export default function grammar() {
2243
2243
  children: [1, 2, 3]
2244
2244
  }; // CAT
2245
2245
  this.rules[69].opcodes[1] = {
2246
- type: 7,
2247
- string: [91]
2248
- }; // TLS
2246
+ type: 4,
2247
+ index: 80
2248
+ }; // RNM(left-bracket)
2249
2249
  this.rules[69].opcodes[2] = {
2250
2250
  type: 4,
2251
2251
  index: 70
2252
2252
  }; // RNM(normal-selector)
2253
2253
  this.rules[69].opcodes[3] = {
2254
- type: 7,
2255
- string: [93]
2256
- }; // TLS
2254
+ type: 4,
2255
+ index: 81
2256
+ }; // RNM(right-bracket)
2257
2257
 
2258
2258
  /* normal-selector */
2259
2259
  this.rules[70].opcodes = [];
@@ -2277,9 +2277,9 @@ export default function grammar() {
2277
2277
  children: [1, 2, 4]
2278
2278
  }; // CAT
2279
2279
  this.rules[71].opcodes[1] = {
2280
- type: 6,
2281
- string: [39]
2282
- }; // TBS
2280
+ type: 4,
2281
+ index: 87
2282
+ }; // RNM(squote)
2283
2283
  this.rules[71].opcodes[2] = {
2284
2284
  type: 3,
2285
2285
  min: 0,
@@ -2290,9 +2290,9 @@ export default function grammar() {
2290
2290
  index: 72
2291
2291
  }; // RNM(normal-single-quoted)
2292
2292
  this.rules[71].opcodes[4] = {
2293
- type: 6,
2294
- string: [39]
2295
- }; // TBS
2293
+ type: 4,
2294
+ index: 87
2295
+ }; // RNM(squote)
2296
2296
 
2297
2297
  /* normal-single-quoted */
2298
2298
  this.rules[72].opcodes = [];
@@ -2780,9 +2780,9 @@ export default function grammar() {
2780
2780
  str += "\n";
2781
2781
  str += "; https://www.rfc-editor.org/rfc/rfc9535#name-normalized-paths\n";
2782
2782
  str += "normalized-path = root-identifier *(normal-index-segment)\n";
2783
- str += "normal-index-segment = \"[\" normal-selector \"]\"\n";
2783
+ str += "normal-index-segment = left-bracket normal-selector right-bracket ; MODIFICATION: surrogate text rule used\n";
2784
2784
  str += "normal-selector = normal-name-selector / normal-index-selector\n";
2785
- str += "normal-name-selector = %x27 *normal-single-quoted %x27 ; 'string'\n";
2785
+ str += "normal-name-selector = squote *normal-single-quoted squote ; 'string', MODIFICATION: surrogate text rule used\n";
2786
2786
  str += "normal-single-quoted = normal-unescaped /\n";
2787
2787
  str += " ESC normal-escapable\n";
2788
2788
  str += "normal-unescaped = ; omit %x0-1F control codes\n";
@@ -4,9 +4,11 @@ import CSTTranslator from "./translators/CSTTranslator.mjs";
4
4
  import JSONPathParseError from "../errors/JSONPathParseError.mjs";
5
5
  const grammar = new Grammar();
6
6
  const parse = (jsonPath, {
7
- translator = new CSTTranslator(),
7
+ normalized = false,
8
8
  stats = false,
9
- trace = false
9
+ trace = false,
10
+ translator = new CSTTranslator(),
11
+ test = 3
10
12
  } = {}) => {
11
13
  if (typeof jsonPath !== 'string') {
12
14
  throw new TypeError('JSONPath must be a string');
@@ -17,7 +19,8 @@ const parse = (jsonPath, {
17
19
  if (translator) parser.ast = translator;
18
20
  if (stats) parser.stats = new Stats();
19
21
  if (trace) parser.trace = new Trace();
20
- const result = parser.parse(grammar, 'jsonpath-query', jsonPath);
22
+ const startRule = normalized ? 'normalized-path' : 'jsonpath-query';
23
+ const result = parser.parse(grammar, startRule, jsonPath);
21
24
  return {
22
25
  result,
23
26
  tree: (_parser$ast = parser.ast) === null || _parser$ast === void 0 ? void 0 : _parser$ast.getTree(),
@@ -77,6 +77,14 @@ class CSTTranslator extends AST {
77
77
  // https://www.rfc-editor.org/rfc/rfc9535#section-2.5.2.1
78
78
  this.callbacks['descendant-segment'] = cstCallback('descendant-segment');
79
79
 
80
+ // https://www.rfc-editor.org/rfc/rfc9535#name-normalized-paths
81
+ this.callbacks['normalized-path'] = cstCallback('normalized-path');
82
+ this.callbacks['normal-index-segment'] = cstCallback('normal-index-segment');
83
+ this.callbacks['normal-selector'] = cstCallback('normal-selector');
84
+ this.callbacks['normal-name-selector'] = cstCallback('normal-name-selector');
85
+ this.callbacks['normal-index-selector'] = cstCallback('normal-index-selector');
86
+ this.callbacks['normal-single-quoted'] = cstCallback('normal-single-quoted');
87
+
80
88
  // Surrogate named rules
81
89
  this.callbacks['dot-prefix'] = cstCallback('text');
82
90
  this.callbacks['double-dot-prefix'] = cstCallback('text');
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "2.0.0",
6
+ "version": "2.1.0",
7
7
  "description": "RCF 9535 implementation of JSONPath",
8
8
  "main": "./cjs/index.cjs",
9
9
  "types": "./types/index.d.ts",
package/types/index.d.ts CHANGED
@@ -4,9 +4,10 @@
4
4
  export function parse(jsonpath: string, options?: ParseOptions): ParseResult;
5
5
 
6
6
  export interface ParseOptions {
7
- readonly translator?: Translator | null;
7
+ readonly normalized?: boolean;
8
8
  readonly stats?: boolean;
9
9
  readonly trace?: boolean;
10
+ readonly translator?: Translator | null;
10
11
  }
11
12
 
12
13
  export interface Translator<TTree = unknown> {