json-p3 1.2.0 → 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 +255 -53
- package/dist/json-p3.esm.js +255 -53
- package/dist/json-p3.iife.js +255 -53
- 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/selectors.d.ts +1 -0
- 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.iife.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
|
|
@@ -642,6 +642,24 @@ var json_p3 = (function (exports) {
|
|
|
642
642
|
resolve: resolve
|
|
643
643
|
});
|
|
644
644
|
|
|
645
|
+
const Nothing = Symbol.for("jsonpath.nothing");
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* ValueType for JSONPath function expression tye system.
|
|
649
|
+
*/
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* Object passed to FilterExpression.evaluate().
|
|
653
|
+
*/
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* A type predicate for an object with a string property.
|
|
657
|
+
*/
|
|
658
|
+
function hasStringKey(value, key) {
|
|
659
|
+
return isObject(value) && Object.hasOwn(value, key);
|
|
660
|
+
}
|
|
661
|
+
const KEY_MARK = "\x02";
|
|
662
|
+
|
|
645
663
|
/**
|
|
646
664
|
* The pair of a JSON value and its location found in the target JSON value.
|
|
647
665
|
*/
|
|
@@ -659,7 +677,7 @@ var json_p3 = (function (exports) {
|
|
|
659
677
|
get path() {
|
|
660
678
|
return (
|
|
661
679
|
// eslint-disable-next-line prefer-template
|
|
662
|
-
"$" + this.location.map(s => isString(s) ?
|
|
680
|
+
"$" + this.location.map(s => isString(s) ? this.decode_name_location(s) : `[${s}]`).join("")
|
|
663
681
|
);
|
|
664
682
|
}
|
|
665
683
|
|
|
@@ -672,6 +690,9 @@ var json_p3 = (function (exports) {
|
|
|
672
690
|
}
|
|
673
691
|
return new JSONPointer(JSONPointer.encode(this.location.map(String)));
|
|
674
692
|
}
|
|
693
|
+
decode_name_location(name) {
|
|
694
|
+
return name.startsWith(KEY_MARK) ? `[~'${name.slice(1).replaceAll("'", "\\'")}']` : `['${name.replaceAll("'", "\\'")}']`;
|
|
695
|
+
}
|
|
675
696
|
}
|
|
676
697
|
|
|
677
698
|
/**
|
|
@@ -751,23 +772,6 @@ var json_p3 = (function (exports) {
|
|
|
751
772
|
}
|
|
752
773
|
}
|
|
753
774
|
|
|
754
|
-
const Nothing = Symbol.for("jsonpath.nothing");
|
|
755
|
-
|
|
756
|
-
/**
|
|
757
|
-
* ValueType for JSONPath function expression tye system.
|
|
758
|
-
*/
|
|
759
|
-
|
|
760
|
-
/**
|
|
761
|
-
* Object passed to FilterExpression.evaluate().
|
|
762
|
-
*/
|
|
763
|
-
|
|
764
|
-
/**
|
|
765
|
-
* A type predicate for an object with a string property.
|
|
766
|
-
*/
|
|
767
|
-
function hasStringKey(value, key) {
|
|
768
|
-
return isObject(value) && Object.hasOwn(value, key);
|
|
769
|
-
}
|
|
770
|
-
|
|
771
775
|
/**
|
|
772
776
|
* Base class for all filter expressions.
|
|
773
777
|
*/
|
|
@@ -1170,7 +1174,8 @@ var json_p3 = (function (exports) {
|
|
|
1170
1174
|
TokenKind["AND"] = "TOKEN_AND";
|
|
1171
1175
|
TokenKind["COLON"] = "TOKEN_COLON";
|
|
1172
1176
|
TokenKind["COMMA"] = "TOKEN_COMMA";
|
|
1173
|
-
TokenKind["CURRENT"] = "
|
|
1177
|
+
TokenKind["CURRENT"] = "TOKEN_CURRENT_VALUE";
|
|
1178
|
+
TokenKind["CURRENT_KEY"] = "TOKEN_CURRENT_KEY";
|
|
1174
1179
|
TokenKind["DDOT"] = "TOKEN_DDOT";
|
|
1175
1180
|
TokenKind["DOT"] = "TOKEN_DOT";
|
|
1176
1181
|
TokenKind["DOUBLE_QUOTE_STRING"] = "TOKEN_DOUBLE_QUOTE_STRING";
|
|
@@ -1184,7 +1189,10 @@ var json_p3 = (function (exports) {
|
|
|
1184
1189
|
TokenKind["GT"] = "TOKEN_GT";
|
|
1185
1190
|
TokenKind["INDEX"] = "TOKEN_INDEX";
|
|
1186
1191
|
TokenKind["KEY"] = "TOKEN_KEY";
|
|
1192
|
+
TokenKind["KEY_DOUBLE_QUOTE_STRING"] = "TOKEN_KEY_DOUBLE_QUOTE_STRING";
|
|
1193
|
+
TokenKind["KEY_SINGLE_QUOTE_STRING"] = "TOKEN_KEY_SINGLE_QUOTE_STRING";
|
|
1187
1194
|
TokenKind["KEYS"] = "TOKEN_KEYS";
|
|
1195
|
+
TokenKind["KEYS_FILTER"] = "TOKEN_KEYS_FILTER";
|
|
1188
1196
|
TokenKind["LBRACKET"] = "TOKEN_LBRACKET";
|
|
1189
1197
|
TokenKind["LE"] = "TOKEN_LE";
|
|
1190
1198
|
TokenKind["LG"] = "TOKEN_LG";
|
|
@@ -1265,6 +1273,7 @@ var json_p3 = (function (exports) {
|
|
|
1265
1273
|
const intPattern = /-?[0-9]+/y;
|
|
1266
1274
|
const namePattern = /[\u0080-\uFFFFa-zA-Z_][\u0080-\uFFFFa-zA-Z0-9_-]*/y;
|
|
1267
1275
|
const whitespace = new Set([" ", "\n", "\t", "\r"]);
|
|
1276
|
+
const nameFirstPattern = /[\u0080-\uFFFFa-zA-Z_]/; // don't set sticky bit
|
|
1268
1277
|
|
|
1269
1278
|
/**
|
|
1270
1279
|
* JSONPath lexical scanner.
|
|
@@ -1337,6 +1346,11 @@ var json_p3 = (function (exports) {
|
|
|
1337
1346
|
if (ch) this.backup();
|
|
1338
1347
|
return ch;
|
|
1339
1348
|
}
|
|
1349
|
+
peekMatch(pattern) {
|
|
1350
|
+
const ch = this.next();
|
|
1351
|
+
if (ch) this.backup();
|
|
1352
|
+
return pattern.test(ch);
|
|
1353
|
+
}
|
|
1340
1354
|
accept(valid) {
|
|
1341
1355
|
const ch = this.next();
|
|
1342
1356
|
if (valid.has(ch)) return true;
|
|
@@ -1466,10 +1480,28 @@ var json_p3 = (function (exports) {
|
|
|
1466
1480
|
l.emit(TokenKind.NAME);
|
|
1467
1481
|
return lexSegment;
|
|
1468
1482
|
}
|
|
1469
|
-
if (!l.environment.strict
|
|
1470
|
-
//
|
|
1471
|
-
|
|
1472
|
-
|
|
1483
|
+
if (!l.environment.strict) {
|
|
1484
|
+
// We're effectively disabling the _key selector_ and _keys filter selector_ if a
|
|
1485
|
+
// custom _keys selector_ is set.
|
|
1486
|
+
if (l.environment.keysPattern.source === "~" && l.peek() === "~") {
|
|
1487
|
+
l.next();
|
|
1488
|
+
if (l.peekMatch(nameFirstPattern)) {
|
|
1489
|
+
// Non-standard key selector
|
|
1490
|
+
l.ignore(); // ignore ~
|
|
1491
|
+
l.acceptMatchRun(namePattern);
|
|
1492
|
+
l.emit(TokenKind.KEY);
|
|
1493
|
+
return lexSegment;
|
|
1494
|
+
} else {
|
|
1495
|
+
// Non-standard keys selector
|
|
1496
|
+
l.emit(TokenKind.KEYS);
|
|
1497
|
+
return lexSegment;
|
|
1498
|
+
}
|
|
1499
|
+
} else if (l.acceptMatchRun(l.environment.keysPattern)) {
|
|
1500
|
+
// NOTE: A custom keys pattern does not play well with other non-standard key selectors.
|
|
1501
|
+
// We leave this here for backwards compatibility.
|
|
1502
|
+
l.emit(TokenKind.KEYS);
|
|
1503
|
+
return lexSegment;
|
|
1504
|
+
}
|
|
1473
1505
|
}
|
|
1474
1506
|
const ch = l.next();
|
|
1475
1507
|
switch (ch) {
|
|
@@ -1494,9 +1526,28 @@ var json_p3 = (function (exports) {
|
|
|
1494
1526
|
l.error("unexpected whitespace after dot");
|
|
1495
1527
|
return null;
|
|
1496
1528
|
}
|
|
1497
|
-
if (!l.environment.strict
|
|
1498
|
-
|
|
1499
|
-
|
|
1529
|
+
if (!l.environment.strict) {
|
|
1530
|
+
// We're effectively disabling the _key selector_ and _keys filter selector_ if a
|
|
1531
|
+
// custom _keys selector_ is set.
|
|
1532
|
+
if (l.environment.keysPattern.source === "~" && l.peek() === "~") {
|
|
1533
|
+
l.next();
|
|
1534
|
+
if (l.peekMatch(nameFirstPattern)) {
|
|
1535
|
+
// Non-standard key selector
|
|
1536
|
+
l.ignore(); // ignore ~
|
|
1537
|
+
l.acceptMatchRun(namePattern);
|
|
1538
|
+
l.emit(TokenKind.KEY);
|
|
1539
|
+
return lexSegment;
|
|
1540
|
+
} else {
|
|
1541
|
+
// Non-standard keys selector
|
|
1542
|
+
l.emit(TokenKind.KEYS);
|
|
1543
|
+
return lexSegment;
|
|
1544
|
+
}
|
|
1545
|
+
} else if (l.acceptMatchRun(l.environment.keysPattern)) {
|
|
1546
|
+
// NOTE: A custom keys pattern does not play well with other non-standard key selectors.
|
|
1547
|
+
// We leave this here for backwards compatibility.
|
|
1548
|
+
l.emit(TokenKind.KEYS);
|
|
1549
|
+
return lexSegment;
|
|
1550
|
+
}
|
|
1500
1551
|
}
|
|
1501
1552
|
if (l.acceptMatchRun(namePattern)) {
|
|
1502
1553
|
l.emit(TokenKind.NAME);
|
|
@@ -1519,8 +1570,25 @@ var json_p3 = (function (exports) {
|
|
|
1519
1570
|
continue;
|
|
1520
1571
|
}
|
|
1521
1572
|
if (!l.environment.strict && l.acceptMatchRun(l.environment.keysPattern)) {
|
|
1522
|
-
l.
|
|
1523
|
-
|
|
1573
|
+
switch (l.peek()) {
|
|
1574
|
+
case "'":
|
|
1575
|
+
l.ignore(); // ~
|
|
1576
|
+
l.next();
|
|
1577
|
+
return lexSingleQuoteKeyString(l);
|
|
1578
|
+
case '"':
|
|
1579
|
+
l.ignore(); // ~
|
|
1580
|
+
l.next();
|
|
1581
|
+
return lexDoubleQuoteKeyString(l);
|
|
1582
|
+
case "?":
|
|
1583
|
+
l.ignore(); // ~
|
|
1584
|
+
l.next();
|
|
1585
|
+
l.emit(TokenKind.KEYS_FILTER);
|
|
1586
|
+
l.filterLevel += 1;
|
|
1587
|
+
return lexInsideFilter;
|
|
1588
|
+
default:
|
|
1589
|
+
l.emit(TokenKind.KEYS);
|
|
1590
|
+
continue;
|
|
1591
|
+
}
|
|
1524
1592
|
}
|
|
1525
1593
|
const ch = l.next();
|
|
1526
1594
|
switch (ch) {
|
|
@@ -1607,7 +1675,7 @@ var json_p3 = (function (exports) {
|
|
|
1607
1675
|
l.emit(TokenKind.CURRENT);
|
|
1608
1676
|
return lexSegment;
|
|
1609
1677
|
case "#":
|
|
1610
|
-
l.emit(TokenKind.
|
|
1678
|
+
l.emit(TokenKind.CURRENT_KEY);
|
|
1611
1679
|
return lexSegment;
|
|
1612
1680
|
case ".":
|
|
1613
1681
|
l.backup();
|
|
@@ -1707,8 +1775,7 @@ var json_p3 = (function (exports) {
|
|
|
1707
1775
|
* @param state - The state function to return control to.
|
|
1708
1776
|
* @returns String tokenizing state function.
|
|
1709
1777
|
*/
|
|
1710
|
-
function makeLexString(quote, state) {
|
|
1711
|
-
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
1778
|
+
function makeLexString(quote, state, token_kind) {
|
|
1712
1779
|
function _lexString(l) {
|
|
1713
1780
|
l.ignore();
|
|
1714
1781
|
if (l.peek() === quote) {
|
|
@@ -1734,7 +1801,7 @@ var json_p3 = (function (exports) {
|
|
|
1734
1801
|
}
|
|
1735
1802
|
if (ch === quote) {
|
|
1736
1803
|
l.backup();
|
|
1737
|
-
l.emit(
|
|
1804
|
+
l.emit(token_kind);
|
|
1738
1805
|
l.next();
|
|
1739
1806
|
l.ignore();
|
|
1740
1807
|
return state;
|
|
@@ -1743,10 +1810,12 @@ var json_p3 = (function (exports) {
|
|
|
1743
1810
|
}
|
|
1744
1811
|
return _lexString;
|
|
1745
1812
|
}
|
|
1746
|
-
const lexSingleQuoteStringInsideBracketSelection = makeLexString("'", lexInsideBracketedSelection);
|
|
1747
|
-
const lexDoubleQuoteStringInsideBracketSelection = makeLexString('"', lexInsideBracketedSelection);
|
|
1748
|
-
const lexSingleQuoteStringInsideFilterExpression = makeLexString("'", lexInsideFilter);
|
|
1749
|
-
const lexDoubleQuoteStringInsideFilterExpression = makeLexString('"', lexInsideFilter);
|
|
1813
|
+
const lexSingleQuoteStringInsideBracketSelection = makeLexString("'", lexInsideBracketedSelection, TokenKind.SINGLE_QUOTE_STRING);
|
|
1814
|
+
const lexDoubleQuoteStringInsideBracketSelection = makeLexString('"', lexInsideBracketedSelection, TokenKind.DOUBLE_QUOTE_STRING);
|
|
1815
|
+
const lexSingleQuoteStringInsideFilterExpression = makeLexString("'", lexInsideFilter, TokenKind.SINGLE_QUOTE_STRING);
|
|
1816
|
+
const lexDoubleQuoteStringInsideFilterExpression = makeLexString('"', lexInsideFilter, TokenKind.DOUBLE_QUOTE_STRING);
|
|
1817
|
+
const lexSingleQuoteKeyString = makeLexString("'", lexInsideBracketedSelection, TokenKind.KEY_SINGLE_QUOTE_STRING);
|
|
1818
|
+
const lexDoubleQuoteKeyString = makeLexString('"', lexInsideBracketedSelection, TokenKind.KEY_DOUBLE_QUOTE_STRING);
|
|
1750
1819
|
|
|
1751
1820
|
/**
|
|
1752
1821
|
* Base class for all JSONPath segments and selectors.
|
|
@@ -1787,7 +1856,7 @@ var json_p3 = (function (exports) {
|
|
|
1787
1856
|
resolve(nodes) {
|
|
1788
1857
|
const rv = [];
|
|
1789
1858
|
for (const node of nodes) {
|
|
1790
|
-
if (hasStringKey(node.value, this.name)) {
|
|
1859
|
+
if (!isArray(node.value) && hasStringKey(node.value, this.name)) {
|
|
1791
1860
|
rv.push(new JSONPathNode(node.value[this.name], node.location.concat(this.name), node.root));
|
|
1792
1861
|
}
|
|
1793
1862
|
}
|
|
@@ -1795,7 +1864,7 @@ var json_p3 = (function (exports) {
|
|
|
1795
1864
|
}
|
|
1796
1865
|
*lazyResolve(nodes) {
|
|
1797
1866
|
for (const node of nodes) {
|
|
1798
|
-
if (hasStringKey(node.value, this.name)) {
|
|
1867
|
+
if (!isArray(node.value) && hasStringKey(node.value, this.name)) {
|
|
1799
1868
|
yield new JSONPathNode(node.value[this.name], node.location.concat(this.name), node.root);
|
|
1800
1869
|
}
|
|
1801
1870
|
}
|
|
@@ -1871,7 +1940,7 @@ var json_p3 = (function (exports) {
|
|
|
1871
1940
|
*lazyResolve(nodes) {
|
|
1872
1941
|
for (const node of nodes) {
|
|
1873
1942
|
if (!isArray(node.value)) continue;
|
|
1874
|
-
for (const [i, value] of this.
|
|
1943
|
+
for (const [i, value] of this.lazySlice(node.value, this.start, this.stop, this.step)) {
|
|
1875
1944
|
yield new JSONPathNode(value, node.location.concat(i), node.root);
|
|
1876
1945
|
}
|
|
1877
1946
|
}
|
|
@@ -1934,6 +2003,45 @@ var json_p3 = (function (exports) {
|
|
|
1934
2003
|
}
|
|
1935
2004
|
return slicedArray;
|
|
1936
2005
|
}
|
|
2006
|
+
|
|
2007
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
2008
|
+
*lazySlice(arr, start, stop, step) {
|
|
2009
|
+
if (!arr.length) return;
|
|
2010
|
+
|
|
2011
|
+
// Handle negative and undefined start values
|
|
2012
|
+
if (start === undefined || start === null) {
|
|
2013
|
+
start = step && step < 0 ? arr.length - 1 : 0;
|
|
2014
|
+
} else if (start < 0) {
|
|
2015
|
+
start = Math.max(arr.length + start, 0);
|
|
2016
|
+
} else {
|
|
2017
|
+
start = Math.min(start, arr.length - 1);
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
// Handle negative and undefined stop values
|
|
2021
|
+
if (stop === undefined || stop === null) {
|
|
2022
|
+
stop = step && step < 0 ? -1 : arr.length;
|
|
2023
|
+
} else if (stop < 0) {
|
|
2024
|
+
stop = Math.max(arr.length + stop, -1);
|
|
2025
|
+
} else {
|
|
2026
|
+
stop = Math.min(stop, arr.length);
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
// Perform the slice
|
|
2030
|
+
if (step === undefined) {
|
|
2031
|
+
// Default to a step of 1
|
|
2032
|
+
for (let i = start; i < stop; i += 1) {
|
|
2033
|
+
yield [i, arr[i]];
|
|
2034
|
+
}
|
|
2035
|
+
} else if (step > 0) {
|
|
2036
|
+
for (let i = start; i < stop; i += step) {
|
|
2037
|
+
yield [i, arr[i]];
|
|
2038
|
+
}
|
|
2039
|
+
} else if (step < 0) {
|
|
2040
|
+
for (let i = start; i > stop; i += step) {
|
|
2041
|
+
yield [i, arr[i]];
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
1937
2045
|
}
|
|
1938
2046
|
class WildcardSelector extends JSONPathSelector {
|
|
1939
2047
|
constructor(environment, token) {
|
|
@@ -2000,8 +2108,6 @@ var json_p3 = (function (exports) {
|
|
|
2000
2108
|
}
|
|
2001
2109
|
}
|
|
2002
2110
|
}
|
|
2003
|
-
|
|
2004
|
-
// console.log(JSON.stringify(rv.map((n: any) => n.value)));
|
|
2005
2111
|
return this.selector.resolve(rv);
|
|
2006
2112
|
}
|
|
2007
2113
|
*lazyResolve(nodes) {
|
|
@@ -2358,6 +2464,38 @@ var json_p3 = (function (exports) {
|
|
|
2358
2464
|
}
|
|
2359
2465
|
}
|
|
2360
2466
|
|
|
2467
|
+
class KeySelector extends JSONPathSelector {
|
|
2468
|
+
constructor(environment, token, key) {
|
|
2469
|
+
let shorthand = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
2470
|
+
super(environment, token);
|
|
2471
|
+
this.environment = environment;
|
|
2472
|
+
this.token = token;
|
|
2473
|
+
this.key = key;
|
|
2474
|
+
this.shorthand = shorthand;
|
|
2475
|
+
}
|
|
2476
|
+
resolve(nodes) {
|
|
2477
|
+
const rv = [];
|
|
2478
|
+
for (const node of nodes) {
|
|
2479
|
+
if (node.value instanceof String || isArray(node.value)) continue;
|
|
2480
|
+
if (isObject(node.value) && hasStringKey(node.value, this.key)) {
|
|
2481
|
+
rv.push(new JSONPathNode(this.key, node.location.concat(`${KEY_MARK}${this.key}`), node.root));
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
return rv;
|
|
2485
|
+
}
|
|
2486
|
+
*lazyResolve(nodes) {
|
|
2487
|
+
for (const node of nodes) {
|
|
2488
|
+
if (node.value instanceof String || isArray(node.value)) continue;
|
|
2489
|
+
if (isObject(node.value) && hasStringKey(node.value, this.key)) {
|
|
2490
|
+
yield new JSONPathNode(this.key, node.location.concat(`${KEY_MARK}${this.key}`), node.root);
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2493
|
+
}
|
|
2494
|
+
toString() {
|
|
2495
|
+
return this.shorthand ? `[~'${this.key.replaceAll("'", "\\'")}']` : `~'${this.key.replaceAll("'", "\\'")}'`;
|
|
2496
|
+
}
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2361
2499
|
/**
|
|
2362
2500
|
* Object property name selector or array index selector.
|
|
2363
2501
|
*/
|
|
@@ -2374,10 +2512,8 @@ var json_p3 = (function (exports) {
|
|
|
2374
2512
|
for (const node of nodes) {
|
|
2375
2513
|
if (node.value instanceof String || isArray(node.value)) continue;
|
|
2376
2514
|
if (isObject(node.value)) {
|
|
2377
|
-
let i = 0;
|
|
2378
2515
|
for (const [key, _] of this.environment.entries(node.value)) {
|
|
2379
|
-
rv.push(new JSONPathNode(key, node.location.concat(
|
|
2380
|
-
i++;
|
|
2516
|
+
rv.push(new JSONPathNode(key, node.location.concat(`${KEY_MARK}${key}`), node.root));
|
|
2381
2517
|
}
|
|
2382
2518
|
}
|
|
2383
2519
|
}
|
|
@@ -2387,10 +2523,8 @@ var json_p3 = (function (exports) {
|
|
|
2387
2523
|
for (const node of nodes) {
|
|
2388
2524
|
if (node.value instanceof String || isArray(node.value)) continue;
|
|
2389
2525
|
if (isObject(node.value)) {
|
|
2390
|
-
let i = 0;
|
|
2391
2526
|
for (const [key, _] of this.environment.entries(node.value)) {
|
|
2392
|
-
yield new JSONPathNode(key, node.location.concat(
|
|
2393
|
-
i++;
|
|
2527
|
+
yield new JSONPathNode(key, node.location.concat(`${KEY_MARK}${key}`), node.root);
|
|
2394
2528
|
}
|
|
2395
2529
|
}
|
|
2396
2530
|
}
|
|
@@ -2399,6 +2533,56 @@ var json_p3 = (function (exports) {
|
|
|
2399
2533
|
return this.shorthand ? "[~]" : "~";
|
|
2400
2534
|
}
|
|
2401
2535
|
}
|
|
2536
|
+
class KeysFilterSelector extends JSONPathSelector {
|
|
2537
|
+
constructor(environment, token, expression) {
|
|
2538
|
+
super(environment, token);
|
|
2539
|
+
this.environment = environment;
|
|
2540
|
+
this.token = token;
|
|
2541
|
+
this.expression = expression;
|
|
2542
|
+
}
|
|
2543
|
+
resolve(nodes) {
|
|
2544
|
+
const rv = [];
|
|
2545
|
+
for (const node of nodes) {
|
|
2546
|
+
if (node.value instanceof String || isArray(node.value)) continue;
|
|
2547
|
+
if (isObject(node.value)) {
|
|
2548
|
+
for (const [key, value] of this.environment.entries(node.value)) {
|
|
2549
|
+
const filterContext = {
|
|
2550
|
+
environment: this.environment,
|
|
2551
|
+
currentValue: value,
|
|
2552
|
+
rootValue: node.root,
|
|
2553
|
+
currentKey: key
|
|
2554
|
+
};
|
|
2555
|
+
if (this.expression.evaluate(filterContext)) {
|
|
2556
|
+
rv.push(new JSONPathNode(key, node.location.concat(`${KEY_MARK}${key}`), node.root));
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
return rv;
|
|
2562
|
+
}
|
|
2563
|
+
*lazyResolve(nodes) {
|
|
2564
|
+
for (const node of nodes) {
|
|
2565
|
+
if (node.value instanceof String || isArray(node.value)) continue;
|
|
2566
|
+
if (isObject(node.value)) {
|
|
2567
|
+
for (const [key, value] of this.environment.entries(node.value)) {
|
|
2568
|
+
const filterContext = {
|
|
2569
|
+
environment: this.environment,
|
|
2570
|
+
currentValue: value,
|
|
2571
|
+
rootValue: node.root,
|
|
2572
|
+
lazy: true,
|
|
2573
|
+
currentKey: key
|
|
2574
|
+
};
|
|
2575
|
+
if (this.expression.evaluate(filterContext)) {
|
|
2576
|
+
yield new JSONPathNode(key, node.location.concat(`${KEY_MARK}${key}`), node.root);
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2582
|
+
toString() {
|
|
2583
|
+
return `~?${this.expression.toString()}`;
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2402
2586
|
|
|
2403
2587
|
const PRECEDENCE_LOWEST = 1;
|
|
2404
2588
|
const PRECEDENCE_LOGICAL_OR = 4;
|
|
@@ -2415,7 +2599,7 @@ var json_p3 = (function (exports) {
|
|
|
2415
2599
|
class Parser {
|
|
2416
2600
|
constructor(environment) {
|
|
2417
2601
|
this.environment = environment;
|
|
2418
|
-
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.
|
|
2602
|
+
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]]);
|
|
2419
2603
|
}
|
|
2420
2604
|
parse(stream) {
|
|
2421
2605
|
if (stream.current.kind === TokenKind.ROOT) stream.next();
|
|
@@ -2447,6 +2631,8 @@ var json_p3 = (function (exports) {
|
|
|
2447
2631
|
return new NameSelector(this.environment, stream.current, stream.current.value, true);
|
|
2448
2632
|
case TokenKind.WILD:
|
|
2449
2633
|
return new WildcardSelector(this.environment, stream.current, true);
|
|
2634
|
+
case TokenKind.KEY:
|
|
2635
|
+
return new KeySelector(this.environment, stream.current, stream.current.value, true);
|
|
2450
2636
|
case TokenKind.KEYS:
|
|
2451
2637
|
return new KeysSelector(this.environment, stream.current, true);
|
|
2452
2638
|
case TokenKind.DDOT:
|
|
@@ -2542,6 +2728,13 @@ var json_p3 = (function (exports) {
|
|
|
2542
2728
|
case TokenKind.WILD:
|
|
2543
2729
|
items.push(new WildcardSelector(this.environment, stream.current));
|
|
2544
2730
|
break;
|
|
2731
|
+
case TokenKind.KEY_SINGLE_QUOTE_STRING:
|
|
2732
|
+
case TokenKind.KEY_DOUBLE_QUOTE_STRING:
|
|
2733
|
+
items.push(new KeySelector(this.environment, stream.current, this.decodeString(stream.current, true), false));
|
|
2734
|
+
break;
|
|
2735
|
+
case TokenKind.KEYS_FILTER:
|
|
2736
|
+
items.push(this.parseFilter(stream, true));
|
|
2737
|
+
break;
|
|
2545
2738
|
case TokenKind.KEYS:
|
|
2546
2739
|
items.push(new KeysSelector(this.environment, stream.current));
|
|
2547
2740
|
break;
|
|
@@ -2562,6 +2755,7 @@ var json_p3 = (function (exports) {
|
|
|
2562
2755
|
return new BracketedSelection(this.environment, token, items);
|
|
2563
2756
|
}
|
|
2564
2757
|
parseFilter(stream) {
|
|
2758
|
+
let keys = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
2565
2759
|
const tok = stream.next();
|
|
2566
2760
|
const expr = this.parseFilterExpression(stream);
|
|
2567
2761
|
if (expr instanceof FunctionExtension) {
|
|
@@ -2570,7 +2764,7 @@ var json_p3 = (function (exports) {
|
|
|
2570
2764
|
throw new JSONPathTypeError(`result of ${expr.name}() must be compared`, expr.token);
|
|
2571
2765
|
}
|
|
2572
2766
|
}
|
|
2573
|
-
return new FilterSelector(this.environment, tok, new LogicalExpression(tok, expr));
|
|
2767
|
+
return keys ? new KeysFilterSelector(this.environment, tok, new LogicalExpression(tok, expr)) : new FilterSelector(this.environment, tok, new LogicalExpression(tok, expr));
|
|
2574
2768
|
}
|
|
2575
2769
|
parseBoolean(stream) {
|
|
2576
2770
|
if (stream.current.kind === TokenKind.FALSE) return new BooleanLiteral(stream.current, false);
|
|
@@ -2605,13 +2799,20 @@ var json_p3 = (function (exports) {
|
|
|
2605
2799
|
return new InfixExpression(tok, left, operator, right);
|
|
2606
2800
|
}
|
|
2607
2801
|
parseGroupedExpression(stream) {
|
|
2608
|
-
stream.
|
|
2802
|
+
if (stream.peek.kind === TokenKind.RPAREN) {
|
|
2803
|
+
throw new JSONPathSyntaxError(`empty paren expression`, stream.current);
|
|
2804
|
+
}
|
|
2805
|
+
stream.next(); // eat open paren
|
|
2806
|
+
|
|
2609
2807
|
let expr = this.parseFilterExpression(stream);
|
|
2610
2808
|
stream.next();
|
|
2611
2809
|
while (stream.current.kind !== TokenKind.RPAREN) {
|
|
2612
2810
|
if (stream.current.kind === TokenKind.EOF) {
|
|
2613
2811
|
throw new JSONPathSyntaxError("unbalanced parentheses", stream.current);
|
|
2614
2812
|
}
|
|
2813
|
+
if (!BINARY_OPERATORS.has(stream.current.kind)) {
|
|
2814
|
+
throw new JSONPathSyntaxError(`expected an expression, found '${stream.current.value}'`, stream.current);
|
|
2815
|
+
}
|
|
2615
2816
|
expr = this.parseInfixExpression(stream, expr);
|
|
2616
2817
|
}
|
|
2617
2818
|
stream.expect(TokenKind.RPAREN);
|
|
@@ -2667,7 +2868,7 @@ var json_p3 = (function (exports) {
|
|
|
2667
2868
|
msg = "end of expression";
|
|
2668
2869
|
break;
|
|
2669
2870
|
default:
|
|
2670
|
-
msg = `'${stream.current.value}`;
|
|
2871
|
+
msg = `'${stream.current.value}'`;
|
|
2671
2872
|
}
|
|
2672
2873
|
throw new JSONPathSyntaxError(`unexpected ${msg}`, stream.current);
|
|
2673
2874
|
}
|
|
@@ -2991,6 +3192,7 @@ var json_p3 = (function (exports) {
|
|
|
2991
3192
|
JSONPathRecursionLimitError: JSONPathRecursionLimitError,
|
|
2992
3193
|
JSONPathSyntaxError: JSONPathSyntaxError,
|
|
2993
3194
|
JSONPathTypeError: JSONPathTypeError,
|
|
3195
|
+
KEY_MARK: KEY_MARK,
|
|
2994
3196
|
Nothing: Nothing,
|
|
2995
3197
|
Token: Token,
|
|
2996
3198
|
TokenKind: TokenKind,
|
|
@@ -3483,7 +3685,7 @@ var json_p3 = (function (exports) {
|
|
|
3483
3685
|
apply: apply
|
|
3484
3686
|
});
|
|
3485
3687
|
|
|
3486
|
-
const version = "1.
|
|
3688
|
+
const version = "1.3.0";
|
|
3487
3689
|
|
|
3488
3690
|
exports.DEFAULT_ENVIRONMENT = DEFAULT_ENVIRONMENT;
|
|
3489
3691
|
exports.FunctionExpressionType = FunctionExpressionType;
|