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.esm.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
|
|
@@ -651,6 +651,30 @@ var index$3 = /*#__PURE__*/Object.freeze({
|
|
|
651
651
|
resolve: resolve
|
|
652
652
|
});
|
|
653
653
|
|
|
654
|
+
/**
|
|
655
|
+
* An identifier that is allowed in both JS and JSONPath.
|
|
656
|
+
* JSONPath identifiers are generally much more permissive than JS ones, but
|
|
657
|
+
* they don't allow the character "$", so we take the intersection of the two
|
|
658
|
+
* when deciding whether to use dot shorthand for canonical serialization of
|
|
659
|
+
* simple names.
|
|
660
|
+
*/
|
|
661
|
+
const SHORTHAND_COMPATIBLE_IDENTIFIER = /^[\p{ID_Start}_]\p{ID_Continue}*$/u;
|
|
662
|
+
|
|
663
|
+
/** Usable in a quoted path. */
|
|
664
|
+
function toQuoted(name) {
|
|
665
|
+
return name.includes("'") && !name.includes('"') ? JSON.stringify(name) : toCanonical(name);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/** Usable in a normalized path. */
|
|
669
|
+
function toCanonical(name) {
|
|
670
|
+
return `'${JSON.stringify(name).slice(1, -1).replaceAll('\\"', '"').replaceAll("'", "\\'")}'`;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/** Usable in a shorthand path. */
|
|
674
|
+
function toShorthand(name) {
|
|
675
|
+
return SHORTHAND_COMPATIBLE_IDENTIFIER.test(name) ? name : null;
|
|
676
|
+
}
|
|
677
|
+
|
|
654
678
|
const Nothing = Symbol.for("jsonpath.nothing");
|
|
655
679
|
|
|
656
680
|
/**
|
|
@@ -658,7 +682,7 @@ const Nothing = Symbol.for("jsonpath.nothing");
|
|
|
658
682
|
*/
|
|
659
683
|
|
|
660
684
|
/**
|
|
661
|
-
* Object passed to FilterExpression.evaluate()
|
|
685
|
+
* Object passed to `FilterExpression.evaluate()`.
|
|
662
686
|
*/
|
|
663
687
|
|
|
664
688
|
/**
|
|
@@ -669,6 +693,14 @@ function hasStringKey(value, key) {
|
|
|
669
693
|
}
|
|
670
694
|
const KEY_MARK = "\x02";
|
|
671
695
|
|
|
696
|
+
/**
|
|
697
|
+
* Options for serializing paths.
|
|
698
|
+
*/
|
|
699
|
+
|
|
700
|
+
const defaultSerializationOptions = {
|
|
701
|
+
form: "pretty"
|
|
702
|
+
};
|
|
703
|
+
|
|
672
704
|
/**
|
|
673
705
|
* The pair of a JSON value and its location found in the target JSON value.
|
|
674
706
|
*/
|
|
@@ -683,10 +715,31 @@ class JSONPathNode {
|
|
|
683
715
|
this.location = location;
|
|
684
716
|
this.root = root;
|
|
685
717
|
}
|
|
718
|
+
|
|
719
|
+
/**
|
|
720
|
+
* @deprecated Use {@link getPath} with `options.form` set to `canonical` instead.
|
|
721
|
+
*/
|
|
686
722
|
get path() {
|
|
723
|
+
return this.getPath({
|
|
724
|
+
form: "canonical"
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/**
|
|
729
|
+
* Get the path to this node in the target JSON value.
|
|
730
|
+
*
|
|
731
|
+
* Given that the path refers to the singular current node, the returned path
|
|
732
|
+
* will always be a normalized path if `options.form` is set to `canonical`,
|
|
733
|
+
* following section 2.7 of RFC 9535.
|
|
734
|
+
*/
|
|
735
|
+
getPath(options) {
|
|
736
|
+
const opts = {
|
|
737
|
+
...defaultSerializationOptions,
|
|
738
|
+
...options
|
|
739
|
+
};
|
|
687
740
|
return (
|
|
688
741
|
// eslint-disable-next-line prefer-template
|
|
689
|
-
"$" + this.location.map(s => isString(s) ? this.
|
|
742
|
+
"$" + this.location.map(s => isString(s) ? this.decodeNameLocation(s, opts) : `[${s}]`).join("")
|
|
690
743
|
);
|
|
691
744
|
}
|
|
692
745
|
|
|
@@ -699,8 +752,16 @@ class JSONPathNode {
|
|
|
699
752
|
}
|
|
700
753
|
return new JSONPointer(JSONPointer.encode(this.location.map(String)));
|
|
701
754
|
}
|
|
702
|
-
|
|
703
|
-
|
|
755
|
+
decodeNameLocation(name, options) {
|
|
756
|
+
const normalized = options.form === "canonical";
|
|
757
|
+
const serialize = normalized ? toCanonical : toQuoted;
|
|
758
|
+
const hasKeyMark = name.startsWith(KEY_MARK);
|
|
759
|
+
if (hasKeyMark) name = name.slice(1);
|
|
760
|
+
const shorthand = toShorthand(name);
|
|
761
|
+
if (hasKeyMark) {
|
|
762
|
+
return normalized || shorthand == null ? `[~${serialize(name)}]` : `.~${shorthand}`;
|
|
763
|
+
}
|
|
764
|
+
return normalized || shorthand == null ? `[${serialize(name)}]` : `.${shorthand}`;
|
|
704
765
|
}
|
|
705
766
|
}
|
|
706
767
|
|
|
@@ -761,8 +822,8 @@ class JSONPathNodeList {
|
|
|
761
822
|
* A normalized path contains only property name and index selectors, and
|
|
762
823
|
* always uses bracketed segments, never shorthand selectors.
|
|
763
824
|
*/
|
|
764
|
-
paths() {
|
|
765
|
-
return this.nodes.map(node => node.
|
|
825
|
+
paths(options) {
|
|
826
|
+
return this.nodes.map(node => node.getPath(options));
|
|
766
827
|
}
|
|
767
828
|
|
|
768
829
|
/**
|
|
@@ -834,7 +895,7 @@ class StringLiteral extends FilterExpressionLiteral {
|
|
|
834
895
|
return this.value;
|
|
835
896
|
}
|
|
836
897
|
toString() {
|
|
837
|
-
return
|
|
898
|
+
return toCanonical(this.value);
|
|
838
899
|
}
|
|
839
900
|
}
|
|
840
901
|
class NumberLiteral extends FilterExpressionLiteral {
|
|
@@ -865,10 +926,13 @@ class PrefixExpression extends FilterExpression {
|
|
|
865
926
|
}
|
|
866
927
|
throw new JSONPathTypeError(`unknown operator '${this.operator}'`, this.token);
|
|
867
928
|
}
|
|
868
|
-
toString() {
|
|
869
|
-
return `${this.operator}${this.right.toString()}`;
|
|
929
|
+
toString(options) {
|
|
930
|
+
return `${this.operator}${this.right.toString(options)}`;
|
|
870
931
|
}
|
|
871
932
|
}
|
|
933
|
+
const PRECEDENCE_LOGICAL_OR$1 = 4;
|
|
934
|
+
const PRECEDENCE_LOGICAL_AND$1 = 5;
|
|
935
|
+
const PRECEDENCE_PREFIX$1 = 7;
|
|
872
936
|
class InfixExpression extends FilterExpression {
|
|
873
937
|
constructor(token, left, operator, right) {
|
|
874
938
|
super(token);
|
|
@@ -891,11 +955,12 @@ class InfixExpression extends FilterExpression {
|
|
|
891
955
|
}
|
|
892
956
|
return compare(left, this.operator, right);
|
|
893
957
|
}
|
|
894
|
-
toString() {
|
|
958
|
+
toString(options) {
|
|
959
|
+
// Note that `LogicalExpression.toString()` does not call this.
|
|
895
960
|
if (this.logical) {
|
|
896
|
-
return `(${this.left.toString()} ${this.operator} ${this.right.toString()})`;
|
|
961
|
+
return `(${this.left.toString(options)} ${this.operator} ${this.right.toString(options)})`;
|
|
897
962
|
}
|
|
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
965
|
}
|
|
901
966
|
class LogicalExpression extends FilterExpression {
|
|
@@ -909,8 +974,38 @@ class LogicalExpression extends FilterExpression {
|
|
|
909
974
|
if (value instanceof JSONPathNodeList) return value.nodes.length > 0; // existence
|
|
910
975
|
return isTruthy(value);
|
|
911
976
|
}
|
|
912
|
-
toString() {
|
|
913
|
-
|
|
977
|
+
toString(options) {
|
|
978
|
+
// Minimize parentheses in logical expressions.
|
|
979
|
+
function _toString(expression, parentPrecedence) {
|
|
980
|
+
if (expression instanceof InfixExpression) {
|
|
981
|
+
let precedence;
|
|
982
|
+
let op;
|
|
983
|
+
let left;
|
|
984
|
+
let right;
|
|
985
|
+
if (expression.operator === "&&") {
|
|
986
|
+
precedence = PRECEDENCE_LOGICAL_AND$1;
|
|
987
|
+
op = "&&";
|
|
988
|
+
left = _toString(expression.left, precedence);
|
|
989
|
+
right = _toString(expression.right, precedence);
|
|
990
|
+
} else if (expression.operator === "||") {
|
|
991
|
+
precedence = PRECEDENCE_LOGICAL_OR$1;
|
|
992
|
+
op = "||";
|
|
993
|
+
left = _toString(expression.left, precedence);
|
|
994
|
+
right = _toString(expression.right, precedence);
|
|
995
|
+
} else {
|
|
996
|
+
return expression.toString(options);
|
|
997
|
+
}
|
|
998
|
+
const expr = `${left} ${op} ${right}`;
|
|
999
|
+
return precedence < parentPrecedence ? `(${expr})` : expr;
|
|
1000
|
+
}
|
|
1001
|
+
if (expression instanceof PrefixExpression) {
|
|
1002
|
+
const operand = _toString(expression.right, PRECEDENCE_PREFIX$1);
|
|
1003
|
+
const expr = `!${operand}`;
|
|
1004
|
+
return parentPrecedence > PRECEDENCE_PREFIX$1 ? `(${expr})` : expr;
|
|
1005
|
+
}
|
|
1006
|
+
return expression.toString(options);
|
|
1007
|
+
}
|
|
1008
|
+
return _toString(this.expression, 0);
|
|
914
1009
|
}
|
|
915
1010
|
}
|
|
916
1011
|
|
|
@@ -928,16 +1023,16 @@ class RelativeQuery extends FilterQuery {
|
|
|
928
1023
|
evaluate(context) {
|
|
929
1024
|
return context.lazy ? new JSONPathNodeList(Array.from(this.path.lazyQuery(context.currentValue))) : this.path.query(context.currentValue);
|
|
930
1025
|
}
|
|
931
|
-
toString() {
|
|
932
|
-
return `@${this.path.toString().slice(1)}`;
|
|
1026
|
+
toString(options) {
|
|
1027
|
+
return `@${this.path.toString(options).slice(1)}`;
|
|
933
1028
|
}
|
|
934
1029
|
}
|
|
935
1030
|
class RootQuery extends FilterQuery {
|
|
936
1031
|
evaluate(context) {
|
|
937
1032
|
return context.lazy ? new JSONPathNodeList(Array.from(this.path.lazyQuery(context.rootValue))) : this.path.query(context.rootValue);
|
|
938
1033
|
}
|
|
939
|
-
toString() {
|
|
940
|
-
return this.path.toString();
|
|
1034
|
+
toString(options) {
|
|
1035
|
+
return this.path.toString(options);
|
|
941
1036
|
}
|
|
942
1037
|
}
|
|
943
1038
|
class FunctionExtension extends FilterExpression {
|
|
@@ -955,8 +1050,8 @@ class FunctionExtension extends FilterExpression {
|
|
|
955
1050
|
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);
|
|
956
1051
|
return func.call(...args);
|
|
957
1052
|
}
|
|
958
|
-
toString() {
|
|
959
|
-
return `${this.name}(${this.args.map(e => e.toString()).join(", ")})`;
|
|
1053
|
+
toString(options) {
|
|
1054
|
+
return `${this.name}(${this.args.map(e => e.toString(options)).join(", ")})`;
|
|
960
1055
|
}
|
|
961
1056
|
unpack_node_list(arg) {
|
|
962
1057
|
switch (arg.length) {
|
|
@@ -2893,7 +2988,6 @@ function lexInsideBracketedSelection(l) {
|
|
|
2893
2988
|
switch (ch) {
|
|
2894
2989
|
case "]":
|
|
2895
2990
|
l.emit(TokenKind.RBRACKET);
|
|
2896
|
-
if (l.filterLevel) return lexInsideFilter;
|
|
2897
2991
|
return lexSegment;
|
|
2898
2992
|
case "":
|
|
2899
2993
|
l.error("unclosed bracketed selection");
|
|
@@ -3163,8 +3257,17 @@ class NameSelector extends JSONPathSelector {
|
|
|
3163
3257
|
yield new JSONPathNode(node.value[this.name], node.location.concat(this.name), node.root);
|
|
3164
3258
|
}
|
|
3165
3259
|
}
|
|
3166
|
-
toString() {
|
|
3167
|
-
|
|
3260
|
+
toString(options) {
|
|
3261
|
+
const {
|
|
3262
|
+
form
|
|
3263
|
+
} = {
|
|
3264
|
+
...defaultSerializationOptions,
|
|
3265
|
+
...options
|
|
3266
|
+
};
|
|
3267
|
+
return form === "canonical" ? toCanonical(this.name) : toQuoted(this.name);
|
|
3268
|
+
}
|
|
3269
|
+
shorthand() {
|
|
3270
|
+
return toShorthand(this.name);
|
|
3168
3271
|
}
|
|
3169
3272
|
}
|
|
3170
3273
|
|
|
@@ -3433,8 +3536,8 @@ class FilterSelector extends JSONPathSelector {
|
|
|
3433
3536
|
}
|
|
3434
3537
|
}
|
|
3435
3538
|
}
|
|
3436
|
-
toString() {
|
|
3437
|
-
return `?${this.expression.toString()}`;
|
|
3539
|
+
toString(options) {
|
|
3540
|
+
return `?${this.expression.toString(options)}`;
|
|
3438
3541
|
}
|
|
3439
3542
|
}
|
|
3440
3543
|
|
|
@@ -3465,7 +3568,7 @@ class JSONPathSegment {
|
|
|
3465
3568
|
*/
|
|
3466
3569
|
|
|
3467
3570
|
/**
|
|
3468
|
-
* Return a
|
|
3571
|
+
* Return a string representation of this segment.
|
|
3469
3572
|
*/
|
|
3470
3573
|
}
|
|
3471
3574
|
|
|
@@ -3487,8 +3590,18 @@ class ChildSegment extends JSONPathSegment {
|
|
|
3487
3590
|
}
|
|
3488
3591
|
}
|
|
3489
3592
|
}
|
|
3490
|
-
toString() {
|
|
3491
|
-
|
|
3593
|
+
toString(options) {
|
|
3594
|
+
const {
|
|
3595
|
+
form
|
|
3596
|
+
} = {
|
|
3597
|
+
...defaultSerializationOptions,
|
|
3598
|
+
...options
|
|
3599
|
+
};
|
|
3600
|
+
if (form === "pretty" && this.selectors.length === 1 && this.selectors[0] instanceof NameSelector) {
|
|
3601
|
+
const shorthand = this.selectors[0].shorthand();
|
|
3602
|
+
if (shorthand != null) return `.${shorthand}`;
|
|
3603
|
+
}
|
|
3604
|
+
return `[${this.selectors.map(s => s.toString(options)).join(", ")}]`;
|
|
3492
3605
|
}
|
|
3493
3606
|
}
|
|
3494
3607
|
|
|
@@ -3515,8 +3628,8 @@ class DescendantSegment extends JSONPathSegment {
|
|
|
3515
3628
|
}
|
|
3516
3629
|
}
|
|
3517
3630
|
}
|
|
3518
|
-
toString() {
|
|
3519
|
-
return `..[${this.selectors.map(s => s.toString()).join(", ")}]`;
|
|
3631
|
+
toString(options) {
|
|
3632
|
+
return `..[${this.selectors.map(s => s.toString(options)).join(", ")}]`;
|
|
3520
3633
|
}
|
|
3521
3634
|
visit(node) {
|
|
3522
3635
|
var _this = this;
|
|
@@ -3616,23 +3729,18 @@ function shuffle(entries) {
|
|
|
3616
3729
|
}
|
|
3617
3730
|
|
|
3618
3731
|
/**
|
|
3619
|
-
*
|
|
3732
|
+
* A compiled JSONPath query ready to be applied to different data repeatedly.
|
|
3620
3733
|
*/
|
|
3621
3734
|
class JSONPathQuery {
|
|
3622
|
-
/**
|
|
3623
|
-
*
|
|
3624
|
-
* @param environment -
|
|
3625
|
-
* @param segments -
|
|
3626
|
-
*/
|
|
3627
3735
|
constructor(environment, segments) {
|
|
3628
3736
|
this.environment = environment;
|
|
3629
3737
|
this.segments = segments;
|
|
3630
3738
|
}
|
|
3631
3739
|
|
|
3632
3740
|
/**
|
|
3633
|
-
*
|
|
3634
|
-
* @param value -
|
|
3635
|
-
* @returns
|
|
3741
|
+
* Apply this JSONPath query to _value_.
|
|
3742
|
+
* @param value - A JSON-like object to apply this query to.
|
|
3743
|
+
* @returns Nodes matched by applying this query to _value_.
|
|
3636
3744
|
*/
|
|
3637
3745
|
query(value) {
|
|
3638
3746
|
let nodes = [new JSONPathNode(value, [], value)];
|
|
@@ -3643,9 +3751,9 @@ class JSONPathQuery {
|
|
|
3643
3751
|
}
|
|
3644
3752
|
|
|
3645
3753
|
/**
|
|
3646
|
-
*
|
|
3647
|
-
* @param value -
|
|
3648
|
-
* @returns
|
|
3754
|
+
* Apply this JSONPath query to _value_.
|
|
3755
|
+
* @param value - A JSON-like object to apply this query to.
|
|
3756
|
+
* @returns An iterator over nodes matched by applying this query to _value_.
|
|
3649
3757
|
*/
|
|
3650
3758
|
lazyQuery(value) {
|
|
3651
3759
|
let nodes = [new JSONPathNode(value, [], value)][Symbol.iterator]();
|
|
@@ -3671,11 +3779,15 @@ class JSONPathQuery {
|
|
|
3671
3779
|
}
|
|
3672
3780
|
|
|
3673
3781
|
/**
|
|
3674
|
-
*
|
|
3782
|
+
* Return a string representation of this query.
|
|
3675
3783
|
*/
|
|
3676
|
-
toString() {
|
|
3677
|
-
return `$${this.segments.map(s => s.toString()).join("")}`;
|
|
3784
|
+
toString(options) {
|
|
3785
|
+
return `$${this.segments.map(s => s.toString(options)).join("")}`;
|
|
3678
3786
|
}
|
|
3787
|
+
|
|
3788
|
+
/**
|
|
3789
|
+
* Return `true` if this query is a _singular query_, or `false` otherwise.
|
|
3790
|
+
*/
|
|
3679
3791
|
singularQuery() {
|
|
3680
3792
|
for (const segment of this.segments) {
|
|
3681
3793
|
if (segment instanceof DescendantSegment) return false;
|
|
@@ -3717,8 +3829,15 @@ class KeySelector extends JSONPathSelector {
|
|
|
3717
3829
|
yield new JSONPathNode(this.key, node.location.concat(`${KEY_MARK}${this.key}`), node.root);
|
|
3718
3830
|
}
|
|
3719
3831
|
}
|
|
3720
|
-
toString() {
|
|
3721
|
-
|
|
3832
|
+
toString(options) {
|
|
3833
|
+
const {
|
|
3834
|
+
form
|
|
3835
|
+
} = {
|
|
3836
|
+
...defaultSerializationOptions,
|
|
3837
|
+
...options
|
|
3838
|
+
};
|
|
3839
|
+
const serialize = form === "canonical" ? toCanonical : toQuoted;
|
|
3840
|
+
return `~${serialize(this.key)}`;
|
|
3722
3841
|
}
|
|
3723
3842
|
}
|
|
3724
3843
|
|
|
@@ -3794,8 +3913,8 @@ class KeysFilterSelector extends JSONPathSelector {
|
|
|
3794
3913
|
}
|
|
3795
3914
|
}
|
|
3796
3915
|
}
|
|
3797
|
-
toString() {
|
|
3798
|
-
return `~?${this.expression.toString()}`;
|
|
3916
|
+
toString(options) {
|
|
3917
|
+
return `~?${this.expression.toString(options)}`;
|
|
3799
3918
|
}
|
|
3800
3919
|
}
|
|
3801
3920
|
|
|
@@ -5085,6 +5204,6 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
5085
5204
|
apply: apply
|
|
5086
5205
|
});
|
|
5087
5206
|
|
|
5088
|
-
const version = "2.
|
|
5207
|
+
const version = "2.1.1";
|
|
5089
5208
|
|
|
5090
5209
|
export { DEFAULT_ENVIRONMENT, FunctionExpressionType, JSONPatch, JSONPatchError, JSONPatchTestFailure, JSONPathEnvironment, JSONPathError, JSONPathIndexError, JSONPathLexerError, JSONPathNode, JSONPathNodeList, JSONPathQuery, JSONPathRecursionLimitError, JSONPathSyntaxError, JSONPathTypeError, JSONPointer, Nothing, RelativeJSONPointer, Token, TokenKind, UNDEFINED, apply, compile, index as jsonpatch, index$1 as jsonpath, index$3 as jsonpointer, lazyQuery, query, resolve, version };
|