json-p3 1.2.1 → 1.3.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/dist/json-p3.cjs.js +204 -46
- package/dist/json-p3.esm.js +204 -46
- package/dist/json-p3.iife.js +204 -46
- package/dist/json-p3.iife.min.js +1 -1
- package/dist/json-p3.iife.min.js.map +1 -1
- package/dist/path/extra/selectors.d.ts +20 -0
- package/dist/path/index.d.ts +1 -1
- package/dist/path/lex.d.ts +1 -0
- package/dist/path/node.d.ts +1 -0
- package/dist/path/parse.d.ts +1 -1
- package/dist/path/token.d.ts +7 -3
- package/dist/path/types.d.ts +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/json-p3.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* json-p3 version 1.
|
|
2
|
+
* json-p3 version 1.3.0
|
|
3
3
|
* https://github.com/jg-rp/json-p3
|
|
4
4
|
*
|
|
5
5
|
* MIT License
|
|
@@ -641,6 +641,24 @@ var index$3 = /*#__PURE__*/Object.freeze({
|
|
|
641
641
|
resolve: resolve
|
|
642
642
|
});
|
|
643
643
|
|
|
644
|
+
const Nothing = Symbol.for("jsonpath.nothing");
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* ValueType for JSONPath function expression tye system.
|
|
648
|
+
*/
|
|
649
|
+
|
|
650
|
+
/**
|
|
651
|
+
* Object passed to FilterExpression.evaluate().
|
|
652
|
+
*/
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* A type predicate for an object with a string property.
|
|
656
|
+
*/
|
|
657
|
+
function hasStringKey(value, key) {
|
|
658
|
+
return isObject(value) && Object.hasOwn(value, key);
|
|
659
|
+
}
|
|
660
|
+
const KEY_MARK = "\x02";
|
|
661
|
+
|
|
644
662
|
/**
|
|
645
663
|
* The pair of a JSON value and its location found in the target JSON value.
|
|
646
664
|
*/
|
|
@@ -658,7 +676,7 @@ class JSONPathNode {
|
|
|
658
676
|
get path() {
|
|
659
677
|
return (
|
|
660
678
|
// eslint-disable-next-line prefer-template
|
|
661
|
-
"$" + this.location.map(s => isString(s) ?
|
|
679
|
+
"$" + this.location.map(s => isString(s) ? this.decode_name_location(s) : `[${s}]`).join("")
|
|
662
680
|
);
|
|
663
681
|
}
|
|
664
682
|
|
|
@@ -671,6 +689,9 @@ class JSONPathNode {
|
|
|
671
689
|
}
|
|
672
690
|
return new JSONPointer(JSONPointer.encode(this.location.map(String)));
|
|
673
691
|
}
|
|
692
|
+
decode_name_location(name) {
|
|
693
|
+
return name.startsWith(KEY_MARK) ? `[~'${name.slice(1).replaceAll("'", "\\'")}']` : `['${name.replaceAll("'", "\\'")}']`;
|
|
694
|
+
}
|
|
674
695
|
}
|
|
675
696
|
|
|
676
697
|
/**
|
|
@@ -750,23 +771,6 @@ class JSONPathNodeList {
|
|
|
750
771
|
}
|
|
751
772
|
}
|
|
752
773
|
|
|
753
|
-
const Nothing = Symbol.for("jsonpath.nothing");
|
|
754
|
-
|
|
755
|
-
/**
|
|
756
|
-
* ValueType for JSONPath function expression tye system.
|
|
757
|
-
*/
|
|
758
|
-
|
|
759
|
-
/**
|
|
760
|
-
* Object passed to FilterExpression.evaluate().
|
|
761
|
-
*/
|
|
762
|
-
|
|
763
|
-
/**
|
|
764
|
-
* A type predicate for an object with a string property.
|
|
765
|
-
*/
|
|
766
|
-
function hasStringKey(value, key) {
|
|
767
|
-
return isObject(value) && Object.hasOwn(value, key);
|
|
768
|
-
}
|
|
769
|
-
|
|
770
774
|
/**
|
|
771
775
|
* Base class for all filter expressions.
|
|
772
776
|
*/
|
|
@@ -1169,7 +1173,8 @@ let TokenKind = /*#__PURE__*/function (TokenKind) {
|
|
|
1169
1173
|
TokenKind["AND"] = "TOKEN_AND";
|
|
1170
1174
|
TokenKind["COLON"] = "TOKEN_COLON";
|
|
1171
1175
|
TokenKind["COMMA"] = "TOKEN_COMMA";
|
|
1172
|
-
TokenKind["CURRENT"] = "
|
|
1176
|
+
TokenKind["CURRENT"] = "TOKEN_CURRENT_VALUE";
|
|
1177
|
+
TokenKind["CURRENT_KEY"] = "TOKEN_CURRENT_KEY";
|
|
1173
1178
|
TokenKind["DDOT"] = "TOKEN_DDOT";
|
|
1174
1179
|
TokenKind["DOT"] = "TOKEN_DOT";
|
|
1175
1180
|
TokenKind["DOUBLE_QUOTE_STRING"] = "TOKEN_DOUBLE_QUOTE_STRING";
|
|
@@ -1183,7 +1188,10 @@ let TokenKind = /*#__PURE__*/function (TokenKind) {
|
|
|
1183
1188
|
TokenKind["GT"] = "TOKEN_GT";
|
|
1184
1189
|
TokenKind["INDEX"] = "TOKEN_INDEX";
|
|
1185
1190
|
TokenKind["KEY"] = "TOKEN_KEY";
|
|
1191
|
+
TokenKind["KEY_DOUBLE_QUOTE_STRING"] = "TOKEN_KEY_DOUBLE_QUOTE_STRING";
|
|
1192
|
+
TokenKind["KEY_SINGLE_QUOTE_STRING"] = "TOKEN_KEY_SINGLE_QUOTE_STRING";
|
|
1186
1193
|
TokenKind["KEYS"] = "TOKEN_KEYS";
|
|
1194
|
+
TokenKind["KEYS_FILTER"] = "TOKEN_KEYS_FILTER";
|
|
1187
1195
|
TokenKind["LBRACKET"] = "TOKEN_LBRACKET";
|
|
1188
1196
|
TokenKind["LE"] = "TOKEN_LE";
|
|
1189
1197
|
TokenKind["LG"] = "TOKEN_LG";
|
|
@@ -1264,6 +1272,7 @@ const indexPattern = /-?\d+/y;
|
|
|
1264
1272
|
const intPattern = /-?[0-9]+/y;
|
|
1265
1273
|
const namePattern = /[\u0080-\uFFFFa-zA-Z_][\u0080-\uFFFFa-zA-Z0-9_-]*/y;
|
|
1266
1274
|
const whitespace = new Set([" ", "\n", "\t", "\r"]);
|
|
1275
|
+
const nameFirstPattern = /[\u0080-\uFFFFa-zA-Z_]/; // don't set sticky bit
|
|
1267
1276
|
|
|
1268
1277
|
/**
|
|
1269
1278
|
* JSONPath lexical scanner.
|
|
@@ -1336,6 +1345,11 @@ class Lexer {
|
|
|
1336
1345
|
if (ch) this.backup();
|
|
1337
1346
|
return ch;
|
|
1338
1347
|
}
|
|
1348
|
+
peekMatch(pattern) {
|
|
1349
|
+
const ch = this.next();
|
|
1350
|
+
if (ch) this.backup();
|
|
1351
|
+
return pattern.test(ch);
|
|
1352
|
+
}
|
|
1339
1353
|
accept(valid) {
|
|
1340
1354
|
const ch = this.next();
|
|
1341
1355
|
if (valid.has(ch)) return true;
|
|
@@ -1465,10 +1479,28 @@ function lexDescendantSelection(l) {
|
|
|
1465
1479
|
l.emit(TokenKind.NAME);
|
|
1466
1480
|
return lexSegment;
|
|
1467
1481
|
}
|
|
1468
|
-
if (!l.environment.strict
|
|
1469
|
-
//
|
|
1470
|
-
|
|
1471
|
-
|
|
1482
|
+
if (!l.environment.strict) {
|
|
1483
|
+
// We're effectively disabling the _key selector_ and _keys filter selector_ if a
|
|
1484
|
+
// custom _keys selector_ is set.
|
|
1485
|
+
if (l.environment.keysPattern.source === "~" && l.peek() === "~") {
|
|
1486
|
+
l.next();
|
|
1487
|
+
if (l.peekMatch(nameFirstPattern)) {
|
|
1488
|
+
// Non-standard key selector
|
|
1489
|
+
l.ignore(); // ignore ~
|
|
1490
|
+
l.acceptMatchRun(namePattern);
|
|
1491
|
+
l.emit(TokenKind.KEY);
|
|
1492
|
+
return lexSegment;
|
|
1493
|
+
} else {
|
|
1494
|
+
// Non-standard keys selector
|
|
1495
|
+
l.emit(TokenKind.KEYS);
|
|
1496
|
+
return lexSegment;
|
|
1497
|
+
}
|
|
1498
|
+
} else if (l.acceptMatchRun(l.environment.keysPattern)) {
|
|
1499
|
+
// NOTE: A custom keys pattern does not play well with other non-standard key selectors.
|
|
1500
|
+
// We leave this here for backwards compatibility.
|
|
1501
|
+
l.emit(TokenKind.KEYS);
|
|
1502
|
+
return lexSegment;
|
|
1503
|
+
}
|
|
1472
1504
|
}
|
|
1473
1505
|
const ch = l.next();
|
|
1474
1506
|
switch (ch) {
|
|
@@ -1493,9 +1525,28 @@ function lexDotSelector(l) {
|
|
|
1493
1525
|
l.error("unexpected whitespace after dot");
|
|
1494
1526
|
return null;
|
|
1495
1527
|
}
|
|
1496
|
-
if (!l.environment.strict
|
|
1497
|
-
|
|
1498
|
-
|
|
1528
|
+
if (!l.environment.strict) {
|
|
1529
|
+
// We're effectively disabling the _key selector_ and _keys filter selector_ if a
|
|
1530
|
+
// custom _keys selector_ is set.
|
|
1531
|
+
if (l.environment.keysPattern.source === "~" && l.peek() === "~") {
|
|
1532
|
+
l.next();
|
|
1533
|
+
if (l.peekMatch(nameFirstPattern)) {
|
|
1534
|
+
// Non-standard key selector
|
|
1535
|
+
l.ignore(); // ignore ~
|
|
1536
|
+
l.acceptMatchRun(namePattern);
|
|
1537
|
+
l.emit(TokenKind.KEY);
|
|
1538
|
+
return lexSegment;
|
|
1539
|
+
} else {
|
|
1540
|
+
// Non-standard keys selector
|
|
1541
|
+
l.emit(TokenKind.KEYS);
|
|
1542
|
+
return lexSegment;
|
|
1543
|
+
}
|
|
1544
|
+
} else if (l.acceptMatchRun(l.environment.keysPattern)) {
|
|
1545
|
+
// NOTE: A custom keys pattern does not play well with other non-standard key selectors.
|
|
1546
|
+
// We leave this here for backwards compatibility.
|
|
1547
|
+
l.emit(TokenKind.KEYS);
|
|
1548
|
+
return lexSegment;
|
|
1549
|
+
}
|
|
1499
1550
|
}
|
|
1500
1551
|
if (l.acceptMatchRun(namePattern)) {
|
|
1501
1552
|
l.emit(TokenKind.NAME);
|
|
@@ -1518,8 +1569,25 @@ function lexInsideBracketedSelection(l) {
|
|
|
1518
1569
|
continue;
|
|
1519
1570
|
}
|
|
1520
1571
|
if (!l.environment.strict && l.acceptMatchRun(l.environment.keysPattern)) {
|
|
1521
|
-
l.
|
|
1522
|
-
|
|
1572
|
+
switch (l.peek()) {
|
|
1573
|
+
case "'":
|
|
1574
|
+
l.ignore(); // ~
|
|
1575
|
+
l.next();
|
|
1576
|
+
return lexSingleQuoteKeyString(l);
|
|
1577
|
+
case '"':
|
|
1578
|
+
l.ignore(); // ~
|
|
1579
|
+
l.next();
|
|
1580
|
+
return lexDoubleQuoteKeyString(l);
|
|
1581
|
+
case "?":
|
|
1582
|
+
l.ignore(); // ~
|
|
1583
|
+
l.next();
|
|
1584
|
+
l.emit(TokenKind.KEYS_FILTER);
|
|
1585
|
+
l.filterLevel += 1;
|
|
1586
|
+
return lexInsideFilter;
|
|
1587
|
+
default:
|
|
1588
|
+
l.emit(TokenKind.KEYS);
|
|
1589
|
+
continue;
|
|
1590
|
+
}
|
|
1523
1591
|
}
|
|
1524
1592
|
const ch = l.next();
|
|
1525
1593
|
switch (ch) {
|
|
@@ -1606,7 +1674,7 @@ function lexInsideFilter(l) {
|
|
|
1606
1674
|
l.emit(TokenKind.CURRENT);
|
|
1607
1675
|
return lexSegment;
|
|
1608
1676
|
case "#":
|
|
1609
|
-
l.emit(TokenKind.
|
|
1677
|
+
l.emit(TokenKind.CURRENT_KEY);
|
|
1610
1678
|
return lexSegment;
|
|
1611
1679
|
case ".":
|
|
1612
1680
|
l.backup();
|
|
@@ -1706,8 +1774,7 @@ function lexInsideFilter(l) {
|
|
|
1706
1774
|
* @param state - The state function to return control to.
|
|
1707
1775
|
* @returns String tokenizing state function.
|
|
1708
1776
|
*/
|
|
1709
|
-
function makeLexString(quote, state) {
|
|
1710
|
-
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
1777
|
+
function makeLexString(quote, state, token_kind) {
|
|
1711
1778
|
function _lexString(l) {
|
|
1712
1779
|
l.ignore();
|
|
1713
1780
|
if (l.peek() === quote) {
|
|
@@ -1733,7 +1800,7 @@ function makeLexString(quote, state) {
|
|
|
1733
1800
|
}
|
|
1734
1801
|
if (ch === quote) {
|
|
1735
1802
|
l.backup();
|
|
1736
|
-
l.emit(
|
|
1803
|
+
l.emit(token_kind);
|
|
1737
1804
|
l.next();
|
|
1738
1805
|
l.ignore();
|
|
1739
1806
|
return state;
|
|
@@ -1742,10 +1809,12 @@ function makeLexString(quote, state) {
|
|
|
1742
1809
|
}
|
|
1743
1810
|
return _lexString;
|
|
1744
1811
|
}
|
|
1745
|
-
const lexSingleQuoteStringInsideBracketSelection = makeLexString("'", lexInsideBracketedSelection);
|
|
1746
|
-
const lexDoubleQuoteStringInsideBracketSelection = makeLexString('"', lexInsideBracketedSelection);
|
|
1747
|
-
const lexSingleQuoteStringInsideFilterExpression = makeLexString("'", lexInsideFilter);
|
|
1748
|
-
const lexDoubleQuoteStringInsideFilterExpression = makeLexString('"', lexInsideFilter);
|
|
1812
|
+
const lexSingleQuoteStringInsideBracketSelection = makeLexString("'", lexInsideBracketedSelection, TokenKind.SINGLE_QUOTE_STRING);
|
|
1813
|
+
const lexDoubleQuoteStringInsideBracketSelection = makeLexString('"', lexInsideBracketedSelection, TokenKind.DOUBLE_QUOTE_STRING);
|
|
1814
|
+
const lexSingleQuoteStringInsideFilterExpression = makeLexString("'", lexInsideFilter, TokenKind.SINGLE_QUOTE_STRING);
|
|
1815
|
+
const lexDoubleQuoteStringInsideFilterExpression = makeLexString('"', lexInsideFilter, TokenKind.DOUBLE_QUOTE_STRING);
|
|
1816
|
+
const lexSingleQuoteKeyString = makeLexString("'", lexInsideBracketedSelection, TokenKind.KEY_SINGLE_QUOTE_STRING);
|
|
1817
|
+
const lexDoubleQuoteKeyString = makeLexString('"', lexInsideBracketedSelection, TokenKind.KEY_DOUBLE_QUOTE_STRING);
|
|
1749
1818
|
|
|
1750
1819
|
/**
|
|
1751
1820
|
* Base class for all JSONPath segments and selectors.
|
|
@@ -2394,6 +2463,38 @@ class CurrentKey extends FilterExpression {
|
|
|
2394
2463
|
}
|
|
2395
2464
|
}
|
|
2396
2465
|
|
|
2466
|
+
class KeySelector extends JSONPathSelector {
|
|
2467
|
+
constructor(environment, token, key) {
|
|
2468
|
+
let shorthand = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
2469
|
+
super(environment, token);
|
|
2470
|
+
this.environment = environment;
|
|
2471
|
+
this.token = token;
|
|
2472
|
+
this.key = key;
|
|
2473
|
+
this.shorthand = shorthand;
|
|
2474
|
+
}
|
|
2475
|
+
resolve(nodes) {
|
|
2476
|
+
const rv = [];
|
|
2477
|
+
for (const node of nodes) {
|
|
2478
|
+
if (node.value instanceof String || isArray(node.value)) continue;
|
|
2479
|
+
if (isObject(node.value) && hasStringKey(node.value, this.key)) {
|
|
2480
|
+
rv.push(new JSONPathNode(this.key, node.location.concat(`${KEY_MARK}${this.key}`), node.root));
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
return rv;
|
|
2484
|
+
}
|
|
2485
|
+
*lazyResolve(nodes) {
|
|
2486
|
+
for (const node of nodes) {
|
|
2487
|
+
if (node.value instanceof String || isArray(node.value)) continue;
|
|
2488
|
+
if (isObject(node.value) && hasStringKey(node.value, this.key)) {
|
|
2489
|
+
yield new JSONPathNode(this.key, node.location.concat(`${KEY_MARK}${this.key}`), node.root);
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2493
|
+
toString() {
|
|
2494
|
+
return this.shorthand ? `[~'${this.key.replaceAll("'", "\\'")}']` : `~'${this.key.replaceAll("'", "\\'")}'`;
|
|
2495
|
+
}
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2397
2498
|
/**
|
|
2398
2499
|
* Object property name selector or array index selector.
|
|
2399
2500
|
*/
|
|
@@ -2410,10 +2511,8 @@ class KeysSelector extends JSONPathSelector {
|
|
|
2410
2511
|
for (const node of nodes) {
|
|
2411
2512
|
if (node.value instanceof String || isArray(node.value)) continue;
|
|
2412
2513
|
if (isObject(node.value)) {
|
|
2413
|
-
let i = 0;
|
|
2414
2514
|
for (const [key, _] of this.environment.entries(node.value)) {
|
|
2415
|
-
rv.push(new JSONPathNode(key, node.location.concat(
|
|
2416
|
-
i++;
|
|
2515
|
+
rv.push(new JSONPathNode(key, node.location.concat(`${KEY_MARK}${key}`), node.root));
|
|
2417
2516
|
}
|
|
2418
2517
|
}
|
|
2419
2518
|
}
|
|
@@ -2423,10 +2522,8 @@ class KeysSelector extends JSONPathSelector {
|
|
|
2423
2522
|
for (const node of nodes) {
|
|
2424
2523
|
if (node.value instanceof String || isArray(node.value)) continue;
|
|
2425
2524
|
if (isObject(node.value)) {
|
|
2426
|
-
let i = 0;
|
|
2427
2525
|
for (const [key, _] of this.environment.entries(node.value)) {
|
|
2428
|
-
yield new JSONPathNode(key, node.location.concat(
|
|
2429
|
-
i++;
|
|
2526
|
+
yield new JSONPathNode(key, node.location.concat(`${KEY_MARK}${key}`), node.root);
|
|
2430
2527
|
}
|
|
2431
2528
|
}
|
|
2432
2529
|
}
|
|
@@ -2435,6 +2532,56 @@ class KeysSelector extends JSONPathSelector {
|
|
|
2435
2532
|
return this.shorthand ? "[~]" : "~";
|
|
2436
2533
|
}
|
|
2437
2534
|
}
|
|
2535
|
+
class KeysFilterSelector extends JSONPathSelector {
|
|
2536
|
+
constructor(environment, token, expression) {
|
|
2537
|
+
super(environment, token);
|
|
2538
|
+
this.environment = environment;
|
|
2539
|
+
this.token = token;
|
|
2540
|
+
this.expression = expression;
|
|
2541
|
+
}
|
|
2542
|
+
resolve(nodes) {
|
|
2543
|
+
const rv = [];
|
|
2544
|
+
for (const node of nodes) {
|
|
2545
|
+
if (node.value instanceof String || isArray(node.value)) continue;
|
|
2546
|
+
if (isObject(node.value)) {
|
|
2547
|
+
for (const [key, value] of this.environment.entries(node.value)) {
|
|
2548
|
+
const filterContext = {
|
|
2549
|
+
environment: this.environment,
|
|
2550
|
+
currentValue: value,
|
|
2551
|
+
rootValue: node.root,
|
|
2552
|
+
currentKey: key
|
|
2553
|
+
};
|
|
2554
|
+
if (this.expression.evaluate(filterContext)) {
|
|
2555
|
+
rv.push(new JSONPathNode(key, node.location.concat(`${KEY_MARK}${key}`), node.root));
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2560
|
+
return rv;
|
|
2561
|
+
}
|
|
2562
|
+
*lazyResolve(nodes) {
|
|
2563
|
+
for (const node of nodes) {
|
|
2564
|
+
if (node.value instanceof String || isArray(node.value)) continue;
|
|
2565
|
+
if (isObject(node.value)) {
|
|
2566
|
+
for (const [key, value] of this.environment.entries(node.value)) {
|
|
2567
|
+
const filterContext = {
|
|
2568
|
+
environment: this.environment,
|
|
2569
|
+
currentValue: value,
|
|
2570
|
+
rootValue: node.root,
|
|
2571
|
+
lazy: true,
|
|
2572
|
+
currentKey: key
|
|
2573
|
+
};
|
|
2574
|
+
if (this.expression.evaluate(filterContext)) {
|
|
2575
|
+
yield new JSONPathNode(key, node.location.concat(`${KEY_MARK}${key}`), node.root);
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
toString() {
|
|
2582
|
+
return `~?${this.expression.toString()}`;
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2438
2585
|
|
|
2439
2586
|
const PRECEDENCE_LOWEST = 1;
|
|
2440
2587
|
const PRECEDENCE_LOGICAL_OR = 4;
|
|
@@ -2451,7 +2598,7 @@ const COMPARISON_OPERATORS = new Set(["==", ">=", ">", "<=", "<", "!="]);
|
|
|
2451
2598
|
class Parser {
|
|
2452
2599
|
constructor(environment) {
|
|
2453
2600
|
this.environment = environment;
|
|
2454
|
-
this.tokenMap = new Map([[TokenKind.FALSE, this.parseBoolean], [TokenKind.NUMBER, this.parseNumber], [TokenKind.LPAREN, this.parseGroupedExpression], [TokenKind.NOT, this.parsePrefixExpression], [TokenKind.NULL, this.parseNull], [TokenKind.ROOT, this.parseRootQuery], [TokenKind.CURRENT, this.parseRelativeQuery], [TokenKind.SINGLE_QUOTE_STRING, this.parseString], [TokenKind.DOUBLE_QUOTE_STRING, this.parseString], [TokenKind.TRUE, this.parseBoolean], [TokenKind.FUNCTION, this.parseFunction], [TokenKind.
|
|
2601
|
+
this.tokenMap = new Map([[TokenKind.FALSE, this.parseBoolean], [TokenKind.NUMBER, this.parseNumber], [TokenKind.LPAREN, this.parseGroupedExpression], [TokenKind.NOT, this.parsePrefixExpression], [TokenKind.NULL, this.parseNull], [TokenKind.ROOT, this.parseRootQuery], [TokenKind.CURRENT, this.parseRelativeQuery], [TokenKind.SINGLE_QUOTE_STRING, this.parseString], [TokenKind.DOUBLE_QUOTE_STRING, this.parseString], [TokenKind.TRUE, this.parseBoolean], [TokenKind.FUNCTION, this.parseFunction], [TokenKind.CURRENT_KEY, this.parseCurrentKey]]);
|
|
2455
2602
|
}
|
|
2456
2603
|
parse(stream) {
|
|
2457
2604
|
if (stream.current.kind === TokenKind.ROOT) stream.next();
|
|
@@ -2483,6 +2630,8 @@ class Parser {
|
|
|
2483
2630
|
return new NameSelector(this.environment, stream.current, stream.current.value, true);
|
|
2484
2631
|
case TokenKind.WILD:
|
|
2485
2632
|
return new WildcardSelector(this.environment, stream.current, true);
|
|
2633
|
+
case TokenKind.KEY:
|
|
2634
|
+
return new KeySelector(this.environment, stream.current, stream.current.value, true);
|
|
2486
2635
|
case TokenKind.KEYS:
|
|
2487
2636
|
return new KeysSelector(this.environment, stream.current, true);
|
|
2488
2637
|
case TokenKind.DDOT:
|
|
@@ -2578,6 +2727,13 @@ class Parser {
|
|
|
2578
2727
|
case TokenKind.WILD:
|
|
2579
2728
|
items.push(new WildcardSelector(this.environment, stream.current));
|
|
2580
2729
|
break;
|
|
2730
|
+
case TokenKind.KEY_SINGLE_QUOTE_STRING:
|
|
2731
|
+
case TokenKind.KEY_DOUBLE_QUOTE_STRING:
|
|
2732
|
+
items.push(new KeySelector(this.environment, stream.current, this.decodeString(stream.current, true), false));
|
|
2733
|
+
break;
|
|
2734
|
+
case TokenKind.KEYS_FILTER:
|
|
2735
|
+
items.push(this.parseFilter(stream, true));
|
|
2736
|
+
break;
|
|
2581
2737
|
case TokenKind.KEYS:
|
|
2582
2738
|
items.push(new KeysSelector(this.environment, stream.current));
|
|
2583
2739
|
break;
|
|
@@ -2598,6 +2754,7 @@ class Parser {
|
|
|
2598
2754
|
return new BracketedSelection(this.environment, token, items);
|
|
2599
2755
|
}
|
|
2600
2756
|
parseFilter(stream) {
|
|
2757
|
+
let keys = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
2601
2758
|
const tok = stream.next();
|
|
2602
2759
|
const expr = this.parseFilterExpression(stream);
|
|
2603
2760
|
if (expr instanceof FunctionExtension) {
|
|
@@ -2606,7 +2763,7 @@ class Parser {
|
|
|
2606
2763
|
throw new JSONPathTypeError(`result of ${expr.name}() must be compared`, expr.token);
|
|
2607
2764
|
}
|
|
2608
2765
|
}
|
|
2609
|
-
return new FilterSelector(this.environment, tok, new LogicalExpression(tok, expr));
|
|
2766
|
+
return keys ? new KeysFilterSelector(this.environment, tok, new LogicalExpression(tok, expr)) : new FilterSelector(this.environment, tok, new LogicalExpression(tok, expr));
|
|
2610
2767
|
}
|
|
2611
2768
|
parseBoolean(stream) {
|
|
2612
2769
|
if (stream.current.kind === TokenKind.FALSE) return new BooleanLiteral(stream.current, false);
|
|
@@ -3034,6 +3191,7 @@ var index$1 = /*#__PURE__*/Object.freeze({
|
|
|
3034
3191
|
JSONPathRecursionLimitError: JSONPathRecursionLimitError,
|
|
3035
3192
|
JSONPathSyntaxError: JSONPathSyntaxError,
|
|
3036
3193
|
JSONPathTypeError: JSONPathTypeError,
|
|
3194
|
+
KEY_MARK: KEY_MARK,
|
|
3037
3195
|
Nothing: Nothing,
|
|
3038
3196
|
Token: Token,
|
|
3039
3197
|
TokenKind: TokenKind,
|
|
@@ -3526,7 +3684,7 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
3526
3684
|
apply: apply
|
|
3527
3685
|
});
|
|
3528
3686
|
|
|
3529
|
-
const version = "1.
|
|
3687
|
+
const version = "1.3.0";
|
|
3530
3688
|
|
|
3531
3689
|
exports.DEFAULT_ENVIRONMENT = DEFAULT_ENVIRONMENT;
|
|
3532
3690
|
exports.FunctionExpressionType = FunctionExpressionType;
|