json-p3 2.0.0 → 2.1.1
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 +170 -51
- package/dist/json-p3.esm.js +170 -51
- package/dist/json-p3.iife.js +170 -51
- package/dist/json-p3.iife.min.js +1 -1
- package/dist/json-p3.iife.min.js.map +1 -1
- package/dist/path/expression.d.ts +8 -8
- package/dist/path/extra/selectors.d.ts +3 -2
- package/dist/path/index.d.ts +1 -1
- package/dist/path/node.d.ts +14 -2
- package/dist/path/path.d.ts +13 -14
- package/dist/path/segments.d.ts +5 -4
- package/dist/path/selectors.d.ts +5 -3
- package/dist/path/serialize.d.ts +6 -0
- package/dist/path/types.d.ts +23 -1
- 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 2.
|
|
2
|
+
* json-p3 version 2.1.1
|
|
3
3
|
* https://github.com/jg-rp/json-p3
|
|
4
4
|
*
|
|
5
5
|
* MIT License
|
|
@@ -653,6 +653,30 @@ var index$3 = /*#__PURE__*/Object.freeze({
|
|
|
653
653
|
resolve: resolve
|
|
654
654
|
});
|
|
655
655
|
|
|
656
|
+
/**
|
|
657
|
+
* An identifier that is allowed in both JS and JSONPath.
|
|
658
|
+
* JSONPath identifiers are generally much more permissive than JS ones, but
|
|
659
|
+
* they don't allow the character "$", so we take the intersection of the two
|
|
660
|
+
* when deciding whether to use dot shorthand for canonical serialization of
|
|
661
|
+
* simple names.
|
|
662
|
+
*/
|
|
663
|
+
const SHORTHAND_COMPATIBLE_IDENTIFIER = /^[\p{ID_Start}_]\p{ID_Continue}*$/u;
|
|
664
|
+
|
|
665
|
+
/** Usable in a quoted path. */
|
|
666
|
+
function toQuoted(name) {
|
|
667
|
+
return name.includes("'") && !name.includes('"') ? JSON.stringify(name) : toCanonical(name);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/** Usable in a normalized path. */
|
|
671
|
+
function toCanonical(name) {
|
|
672
|
+
return `'${JSON.stringify(name).slice(1, -1).replaceAll('\\"', '"').replaceAll("'", "\\'")}'`;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/** Usable in a shorthand path. */
|
|
676
|
+
function toShorthand(name) {
|
|
677
|
+
return SHORTHAND_COMPATIBLE_IDENTIFIER.test(name) ? name : null;
|
|
678
|
+
}
|
|
679
|
+
|
|
656
680
|
const Nothing = Symbol.for("jsonpath.nothing");
|
|
657
681
|
|
|
658
682
|
/**
|
|
@@ -660,7 +684,7 @@ const Nothing = Symbol.for("jsonpath.nothing");
|
|
|
660
684
|
*/
|
|
661
685
|
|
|
662
686
|
/**
|
|
663
|
-
* Object passed to FilterExpression.evaluate()
|
|
687
|
+
* Object passed to `FilterExpression.evaluate()`.
|
|
664
688
|
*/
|
|
665
689
|
|
|
666
690
|
/**
|
|
@@ -671,6 +695,14 @@ function hasStringKey(value, key) {
|
|
|
671
695
|
}
|
|
672
696
|
const KEY_MARK = "\x02";
|
|
673
697
|
|
|
698
|
+
/**
|
|
699
|
+
* Options for serializing paths.
|
|
700
|
+
*/
|
|
701
|
+
|
|
702
|
+
const defaultSerializationOptions = {
|
|
703
|
+
form: "pretty"
|
|
704
|
+
};
|
|
705
|
+
|
|
674
706
|
/**
|
|
675
707
|
* The pair of a JSON value and its location found in the target JSON value.
|
|
676
708
|
*/
|
|
@@ -685,10 +717,31 @@ class JSONPathNode {
|
|
|
685
717
|
this.location = location;
|
|
686
718
|
this.root = root;
|
|
687
719
|
}
|
|
720
|
+
|
|
721
|
+
/**
|
|
722
|
+
* @deprecated Use {@link getPath} with `options.form` set to `canonical` instead.
|
|
723
|
+
*/
|
|
688
724
|
get path() {
|
|
725
|
+
return this.getPath({
|
|
726
|
+
form: "canonical"
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Get the path to this node in the target JSON value.
|
|
732
|
+
*
|
|
733
|
+
* Given that the path refers to the singular current node, the returned path
|
|
734
|
+
* will always be a normalized path if `options.form` is set to `canonical`,
|
|
735
|
+
* following section 2.7 of RFC 9535.
|
|
736
|
+
*/
|
|
737
|
+
getPath(options) {
|
|
738
|
+
const opts = {
|
|
739
|
+
...defaultSerializationOptions,
|
|
740
|
+
...options
|
|
741
|
+
};
|
|
689
742
|
return (
|
|
690
743
|
// eslint-disable-next-line prefer-template
|
|
691
|
-
"$" + this.location.map(s => isString(s) ? this.
|
|
744
|
+
"$" + this.location.map(s => isString(s) ? this.decodeNameLocation(s, opts) : `[${s}]`).join("")
|
|
692
745
|
);
|
|
693
746
|
}
|
|
694
747
|
|
|
@@ -701,8 +754,16 @@ class JSONPathNode {
|
|
|
701
754
|
}
|
|
702
755
|
return new JSONPointer(JSONPointer.encode(this.location.map(String)));
|
|
703
756
|
}
|
|
704
|
-
|
|
705
|
-
|
|
757
|
+
decodeNameLocation(name, options) {
|
|
758
|
+
const normalized = options.form === "canonical";
|
|
759
|
+
const serialize = normalized ? toCanonical : toQuoted;
|
|
760
|
+
const hasKeyMark = name.startsWith(KEY_MARK);
|
|
761
|
+
if (hasKeyMark) name = name.slice(1);
|
|
762
|
+
const shorthand = toShorthand(name);
|
|
763
|
+
if (hasKeyMark) {
|
|
764
|
+
return normalized || shorthand == null ? `[~${serialize(name)}]` : `.~${shorthand}`;
|
|
765
|
+
}
|
|
766
|
+
return normalized || shorthand == null ? `[${serialize(name)}]` : `.${shorthand}`;
|
|
706
767
|
}
|
|
707
768
|
}
|
|
708
769
|
|
|
@@ -763,8 +824,8 @@ class JSONPathNodeList {
|
|
|
763
824
|
* A normalized path contains only property name and index selectors, and
|
|
764
825
|
* always uses bracketed segments, never shorthand selectors.
|
|
765
826
|
*/
|
|
766
|
-
paths() {
|
|
767
|
-
return this.nodes.map(node => node.
|
|
827
|
+
paths(options) {
|
|
828
|
+
return this.nodes.map(node => node.getPath(options));
|
|
768
829
|
}
|
|
769
830
|
|
|
770
831
|
/**
|
|
@@ -836,7 +897,7 @@ class StringLiteral extends FilterExpressionLiteral {
|
|
|
836
897
|
return this.value;
|
|
837
898
|
}
|
|
838
899
|
toString() {
|
|
839
|
-
return
|
|
900
|
+
return toCanonical(this.value);
|
|
840
901
|
}
|
|
841
902
|
}
|
|
842
903
|
class NumberLiteral extends FilterExpressionLiteral {
|
|
@@ -867,10 +928,13 @@ class PrefixExpression extends FilterExpression {
|
|
|
867
928
|
}
|
|
868
929
|
throw new JSONPathTypeError(`unknown operator '${this.operator}'`, this.token);
|
|
869
930
|
}
|
|
870
|
-
toString() {
|
|
871
|
-
return `${this.operator}${this.right.toString()}`;
|
|
931
|
+
toString(options) {
|
|
932
|
+
return `${this.operator}${this.right.toString(options)}`;
|
|
872
933
|
}
|
|
873
934
|
}
|
|
935
|
+
const PRECEDENCE_LOGICAL_OR$1 = 4;
|
|
936
|
+
const PRECEDENCE_LOGICAL_AND$1 = 5;
|
|
937
|
+
const PRECEDENCE_PREFIX$1 = 7;
|
|
874
938
|
class InfixExpression extends FilterExpression {
|
|
875
939
|
constructor(token, left, operator, right) {
|
|
876
940
|
super(token);
|
|
@@ -893,11 +957,12 @@ class InfixExpression extends FilterExpression {
|
|
|
893
957
|
}
|
|
894
958
|
return compare(left, this.operator, right);
|
|
895
959
|
}
|
|
896
|
-
toString() {
|
|
960
|
+
toString(options) {
|
|
961
|
+
// Note that `LogicalExpression.toString()` does not call this.
|
|
897
962
|
if (this.logical) {
|
|
898
|
-
return `(${this.left.toString()} ${this.operator} ${this.right.toString()})`;
|
|
963
|
+
return `(${this.left.toString(options)} ${this.operator} ${this.right.toString(options)})`;
|
|
899
964
|
}
|
|
900
|
-
return `${this.left.toString()} ${this.operator} ${this.right.toString()}`;
|
|
965
|
+
return `${this.left.toString(options)} ${this.operator} ${this.right.toString(options)}`;
|
|
901
966
|
}
|
|
902
967
|
}
|
|
903
968
|
class LogicalExpression extends FilterExpression {
|
|
@@ -911,8 +976,38 @@ class LogicalExpression extends FilterExpression {
|
|
|
911
976
|
if (value instanceof JSONPathNodeList) return value.nodes.length > 0; // existence
|
|
912
977
|
return isTruthy(value);
|
|
913
978
|
}
|
|
914
|
-
toString() {
|
|
915
|
-
|
|
979
|
+
toString(options) {
|
|
980
|
+
// Minimize parentheses in logical expressions.
|
|
981
|
+
function _toString(expression, parentPrecedence) {
|
|
982
|
+
if (expression instanceof InfixExpression) {
|
|
983
|
+
let precedence;
|
|
984
|
+
let op;
|
|
985
|
+
let left;
|
|
986
|
+
let right;
|
|
987
|
+
if (expression.operator === "&&") {
|
|
988
|
+
precedence = PRECEDENCE_LOGICAL_AND$1;
|
|
989
|
+
op = "&&";
|
|
990
|
+
left = _toString(expression.left, precedence);
|
|
991
|
+
right = _toString(expression.right, precedence);
|
|
992
|
+
} else if (expression.operator === "||") {
|
|
993
|
+
precedence = PRECEDENCE_LOGICAL_OR$1;
|
|
994
|
+
op = "||";
|
|
995
|
+
left = _toString(expression.left, precedence);
|
|
996
|
+
right = _toString(expression.right, precedence);
|
|
997
|
+
} else {
|
|
998
|
+
return expression.toString(options);
|
|
999
|
+
}
|
|
1000
|
+
const expr = `${left} ${op} ${right}`;
|
|
1001
|
+
return precedence < parentPrecedence ? `(${expr})` : expr;
|
|
1002
|
+
}
|
|
1003
|
+
if (expression instanceof PrefixExpression) {
|
|
1004
|
+
const operand = _toString(expression.right, PRECEDENCE_PREFIX$1);
|
|
1005
|
+
const expr = `!${operand}`;
|
|
1006
|
+
return parentPrecedence > PRECEDENCE_PREFIX$1 ? `(${expr})` : expr;
|
|
1007
|
+
}
|
|
1008
|
+
return expression.toString(options);
|
|
1009
|
+
}
|
|
1010
|
+
return _toString(this.expression, 0);
|
|
916
1011
|
}
|
|
917
1012
|
}
|
|
918
1013
|
|
|
@@ -930,16 +1025,16 @@ class RelativeQuery extends FilterQuery {
|
|
|
930
1025
|
evaluate(context) {
|
|
931
1026
|
return context.lazy ? new JSONPathNodeList(Array.from(this.path.lazyQuery(context.currentValue))) : this.path.query(context.currentValue);
|
|
932
1027
|
}
|
|
933
|
-
toString() {
|
|
934
|
-
return `@${this.path.toString().slice(1)}`;
|
|
1028
|
+
toString(options) {
|
|
1029
|
+
return `@${this.path.toString(options).slice(1)}`;
|
|
935
1030
|
}
|
|
936
1031
|
}
|
|
937
1032
|
class RootQuery extends FilterQuery {
|
|
938
1033
|
evaluate(context) {
|
|
939
1034
|
return context.lazy ? new JSONPathNodeList(Array.from(this.path.lazyQuery(context.rootValue))) : this.path.query(context.rootValue);
|
|
940
1035
|
}
|
|
941
|
-
toString() {
|
|
942
|
-
return this.path.toString();
|
|
1036
|
+
toString(options) {
|
|
1037
|
+
return this.path.toString(options);
|
|
943
1038
|
}
|
|
944
1039
|
}
|
|
945
1040
|
class FunctionExtension extends FilterExpression {
|
|
@@ -957,8 +1052,8 @@ class FunctionExtension extends FilterExpression {
|
|
|
957
1052
|
const args = this.args.map(arg => arg.evaluate(context)).map((arg, idx) => func.argTypes[idx] !== FunctionExpressionType.NodesType && arg instanceof JSONPathNodeList ? this.unpack_node_list(arg) : arg);
|
|
958
1053
|
return func.call(...args);
|
|
959
1054
|
}
|
|
960
|
-
toString() {
|
|
961
|
-
return `${this.name}(${this.args.map(e => e.toString()).join(", ")})`;
|
|
1055
|
+
toString(options) {
|
|
1056
|
+
return `${this.name}(${this.args.map(e => e.toString(options)).join(", ")})`;
|
|
962
1057
|
}
|
|
963
1058
|
unpack_node_list(arg) {
|
|
964
1059
|
switch (arg.length) {
|
|
@@ -2895,7 +2990,6 @@ function lexInsideBracketedSelection(l) {
|
|
|
2895
2990
|
switch (ch) {
|
|
2896
2991
|
case "]":
|
|
2897
2992
|
l.emit(TokenKind.RBRACKET);
|
|
2898
|
-
if (l.filterLevel) return lexInsideFilter;
|
|
2899
2993
|
return lexSegment;
|
|
2900
2994
|
case "":
|
|
2901
2995
|
l.error("unclosed bracketed selection");
|
|
@@ -3165,8 +3259,17 @@ class NameSelector extends JSONPathSelector {
|
|
|
3165
3259
|
yield new JSONPathNode(node.value[this.name], node.location.concat(this.name), node.root);
|
|
3166
3260
|
}
|
|
3167
3261
|
}
|
|
3168
|
-
toString() {
|
|
3169
|
-
|
|
3262
|
+
toString(options) {
|
|
3263
|
+
const {
|
|
3264
|
+
form
|
|
3265
|
+
} = {
|
|
3266
|
+
...defaultSerializationOptions,
|
|
3267
|
+
...options
|
|
3268
|
+
};
|
|
3269
|
+
return form === "canonical" ? toCanonical(this.name) : toQuoted(this.name);
|
|
3270
|
+
}
|
|
3271
|
+
shorthand() {
|
|
3272
|
+
return toShorthand(this.name);
|
|
3170
3273
|
}
|
|
3171
3274
|
}
|
|
3172
3275
|
|
|
@@ -3435,8 +3538,8 @@ class FilterSelector extends JSONPathSelector {
|
|
|
3435
3538
|
}
|
|
3436
3539
|
}
|
|
3437
3540
|
}
|
|
3438
|
-
toString() {
|
|
3439
|
-
return `?${this.expression.toString()}`;
|
|
3541
|
+
toString(options) {
|
|
3542
|
+
return `?${this.expression.toString(options)}`;
|
|
3440
3543
|
}
|
|
3441
3544
|
}
|
|
3442
3545
|
|
|
@@ -3467,7 +3570,7 @@ class JSONPathSegment {
|
|
|
3467
3570
|
*/
|
|
3468
3571
|
|
|
3469
3572
|
/**
|
|
3470
|
-
* Return a
|
|
3573
|
+
* Return a string representation of this segment.
|
|
3471
3574
|
*/
|
|
3472
3575
|
}
|
|
3473
3576
|
|
|
@@ -3489,8 +3592,18 @@ class ChildSegment extends JSONPathSegment {
|
|
|
3489
3592
|
}
|
|
3490
3593
|
}
|
|
3491
3594
|
}
|
|
3492
|
-
toString() {
|
|
3493
|
-
|
|
3595
|
+
toString(options) {
|
|
3596
|
+
const {
|
|
3597
|
+
form
|
|
3598
|
+
} = {
|
|
3599
|
+
...defaultSerializationOptions,
|
|
3600
|
+
...options
|
|
3601
|
+
};
|
|
3602
|
+
if (form === "pretty" && this.selectors.length === 1 && this.selectors[0] instanceof NameSelector) {
|
|
3603
|
+
const shorthand = this.selectors[0].shorthand();
|
|
3604
|
+
if (shorthand != null) return `.${shorthand}`;
|
|
3605
|
+
}
|
|
3606
|
+
return `[${this.selectors.map(s => s.toString(options)).join(", ")}]`;
|
|
3494
3607
|
}
|
|
3495
3608
|
}
|
|
3496
3609
|
|
|
@@ -3517,8 +3630,8 @@ class DescendantSegment extends JSONPathSegment {
|
|
|
3517
3630
|
}
|
|
3518
3631
|
}
|
|
3519
3632
|
}
|
|
3520
|
-
toString() {
|
|
3521
|
-
return `..[${this.selectors.map(s => s.toString()).join(", ")}]`;
|
|
3633
|
+
toString(options) {
|
|
3634
|
+
return `..[${this.selectors.map(s => s.toString(options)).join(", ")}]`;
|
|
3522
3635
|
}
|
|
3523
3636
|
visit(node) {
|
|
3524
3637
|
var _this = this;
|
|
@@ -3618,23 +3731,18 @@ function shuffle(entries) {
|
|
|
3618
3731
|
}
|
|
3619
3732
|
|
|
3620
3733
|
/**
|
|
3621
|
-
*
|
|
3734
|
+
* A compiled JSONPath query ready to be applied to different data repeatedly.
|
|
3622
3735
|
*/
|
|
3623
3736
|
class JSONPathQuery {
|
|
3624
|
-
/**
|
|
3625
|
-
*
|
|
3626
|
-
* @param environment -
|
|
3627
|
-
* @param segments -
|
|
3628
|
-
*/
|
|
3629
3737
|
constructor(environment, segments) {
|
|
3630
3738
|
this.environment = environment;
|
|
3631
3739
|
this.segments = segments;
|
|
3632
3740
|
}
|
|
3633
3741
|
|
|
3634
3742
|
/**
|
|
3635
|
-
*
|
|
3636
|
-
* @param value -
|
|
3637
|
-
* @returns
|
|
3743
|
+
* Apply this JSONPath query to _value_.
|
|
3744
|
+
* @param value - A JSON-like object to apply this query to.
|
|
3745
|
+
* @returns Nodes matched by applying this query to _value_.
|
|
3638
3746
|
*/
|
|
3639
3747
|
query(value) {
|
|
3640
3748
|
let nodes = [new JSONPathNode(value, [], value)];
|
|
@@ -3645,9 +3753,9 @@ class JSONPathQuery {
|
|
|
3645
3753
|
}
|
|
3646
3754
|
|
|
3647
3755
|
/**
|
|
3648
|
-
*
|
|
3649
|
-
* @param value -
|
|
3650
|
-
* @returns
|
|
3756
|
+
* Apply this JSONPath query to _value_.
|
|
3757
|
+
* @param value - A JSON-like object to apply this query to.
|
|
3758
|
+
* @returns An iterator over nodes matched by applying this query to _value_.
|
|
3651
3759
|
*/
|
|
3652
3760
|
lazyQuery(value) {
|
|
3653
3761
|
let nodes = [new JSONPathNode(value, [], value)][Symbol.iterator]();
|
|
@@ -3673,11 +3781,15 @@ class JSONPathQuery {
|
|
|
3673
3781
|
}
|
|
3674
3782
|
|
|
3675
3783
|
/**
|
|
3676
|
-
*
|
|
3784
|
+
* Return a string representation of this query.
|
|
3677
3785
|
*/
|
|
3678
|
-
toString() {
|
|
3679
|
-
return `$${this.segments.map(s => s.toString()).join("")}`;
|
|
3786
|
+
toString(options) {
|
|
3787
|
+
return `$${this.segments.map(s => s.toString(options)).join("")}`;
|
|
3680
3788
|
}
|
|
3789
|
+
|
|
3790
|
+
/**
|
|
3791
|
+
* Return `true` if this query is a _singular query_, or `false` otherwise.
|
|
3792
|
+
*/
|
|
3681
3793
|
singularQuery() {
|
|
3682
3794
|
for (const segment of this.segments) {
|
|
3683
3795
|
if (segment instanceof DescendantSegment) return false;
|
|
@@ -3719,8 +3831,15 @@ class KeySelector extends JSONPathSelector {
|
|
|
3719
3831
|
yield new JSONPathNode(this.key, node.location.concat(`${KEY_MARK}${this.key}`), node.root);
|
|
3720
3832
|
}
|
|
3721
3833
|
}
|
|
3722
|
-
toString() {
|
|
3723
|
-
|
|
3834
|
+
toString(options) {
|
|
3835
|
+
const {
|
|
3836
|
+
form
|
|
3837
|
+
} = {
|
|
3838
|
+
...defaultSerializationOptions,
|
|
3839
|
+
...options
|
|
3840
|
+
};
|
|
3841
|
+
const serialize = form === "canonical" ? toCanonical : toQuoted;
|
|
3842
|
+
return `~${serialize(this.key)}`;
|
|
3724
3843
|
}
|
|
3725
3844
|
}
|
|
3726
3845
|
|
|
@@ -3796,8 +3915,8 @@ class KeysFilterSelector extends JSONPathSelector {
|
|
|
3796
3915
|
}
|
|
3797
3916
|
}
|
|
3798
3917
|
}
|
|
3799
|
-
toString() {
|
|
3800
|
-
return `~?${this.expression.toString()}`;
|
|
3918
|
+
toString(options) {
|
|
3919
|
+
return `~?${this.expression.toString(options)}`;
|
|
3801
3920
|
}
|
|
3802
3921
|
}
|
|
3803
3922
|
|
|
@@ -5087,7 +5206,7 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
5087
5206
|
apply: apply
|
|
5088
5207
|
});
|
|
5089
5208
|
|
|
5090
|
-
const version = "2.
|
|
5209
|
+
const version = "2.1.1";
|
|
5091
5210
|
|
|
5092
5211
|
exports.DEFAULT_ENVIRONMENT = DEFAULT_ENVIRONMENT;
|
|
5093
5212
|
exports.FunctionExpressionType = FunctionExpressionType;
|