json-p3 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/dist/json-p3.cjs.js +170 -50
- package/dist/json-p3.esm.js +170 -50
- package/dist/json-p3.iife.js +170 -50
- 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.0
|
|
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) {
|
|
@@ -3163,8 +3258,17 @@ class NameSelector extends JSONPathSelector {
|
|
|
3163
3258
|
yield new JSONPathNode(node.value[this.name], node.location.concat(this.name), node.root);
|
|
3164
3259
|
}
|
|
3165
3260
|
}
|
|
3166
|
-
toString() {
|
|
3167
|
-
|
|
3261
|
+
toString(options) {
|
|
3262
|
+
const {
|
|
3263
|
+
form
|
|
3264
|
+
} = {
|
|
3265
|
+
...defaultSerializationOptions,
|
|
3266
|
+
...options
|
|
3267
|
+
};
|
|
3268
|
+
return form === "canonical" ? toCanonical(this.name) : toQuoted(this.name);
|
|
3269
|
+
}
|
|
3270
|
+
shorthand() {
|
|
3271
|
+
return toShorthand(this.name);
|
|
3168
3272
|
}
|
|
3169
3273
|
}
|
|
3170
3274
|
|
|
@@ -3433,8 +3537,8 @@ class FilterSelector extends JSONPathSelector {
|
|
|
3433
3537
|
}
|
|
3434
3538
|
}
|
|
3435
3539
|
}
|
|
3436
|
-
toString() {
|
|
3437
|
-
return `?${this.expression.toString()}`;
|
|
3540
|
+
toString(options) {
|
|
3541
|
+
return `?${this.expression.toString(options)}`;
|
|
3438
3542
|
}
|
|
3439
3543
|
}
|
|
3440
3544
|
|
|
@@ -3465,7 +3569,7 @@ class JSONPathSegment {
|
|
|
3465
3569
|
*/
|
|
3466
3570
|
|
|
3467
3571
|
/**
|
|
3468
|
-
* Return a
|
|
3572
|
+
* Return a string representation of this segment.
|
|
3469
3573
|
*/
|
|
3470
3574
|
}
|
|
3471
3575
|
|
|
@@ -3487,8 +3591,18 @@ class ChildSegment extends JSONPathSegment {
|
|
|
3487
3591
|
}
|
|
3488
3592
|
}
|
|
3489
3593
|
}
|
|
3490
|
-
toString() {
|
|
3491
|
-
|
|
3594
|
+
toString(options) {
|
|
3595
|
+
const {
|
|
3596
|
+
form
|
|
3597
|
+
} = {
|
|
3598
|
+
...defaultSerializationOptions,
|
|
3599
|
+
...options
|
|
3600
|
+
};
|
|
3601
|
+
if (form === "pretty" && this.selectors.length === 1 && this.selectors[0] instanceof NameSelector) {
|
|
3602
|
+
const shorthand = this.selectors[0].shorthand();
|
|
3603
|
+
if (shorthand != null) return `.${shorthand}`;
|
|
3604
|
+
}
|
|
3605
|
+
return `[${this.selectors.map(s => s.toString(options)).join(", ")}]`;
|
|
3492
3606
|
}
|
|
3493
3607
|
}
|
|
3494
3608
|
|
|
@@ -3515,8 +3629,8 @@ class DescendantSegment extends JSONPathSegment {
|
|
|
3515
3629
|
}
|
|
3516
3630
|
}
|
|
3517
3631
|
}
|
|
3518
|
-
toString() {
|
|
3519
|
-
return `..[${this.selectors.map(s => s.toString()).join(", ")}]`;
|
|
3632
|
+
toString(options) {
|
|
3633
|
+
return `..[${this.selectors.map(s => s.toString(options)).join(", ")}]`;
|
|
3520
3634
|
}
|
|
3521
3635
|
visit(node) {
|
|
3522
3636
|
var _this = this;
|
|
@@ -3616,23 +3730,18 @@ function shuffle(entries) {
|
|
|
3616
3730
|
}
|
|
3617
3731
|
|
|
3618
3732
|
/**
|
|
3619
|
-
*
|
|
3733
|
+
* A compiled JSONPath query ready to be applied to different data repeatedly.
|
|
3620
3734
|
*/
|
|
3621
3735
|
class JSONPathQuery {
|
|
3622
|
-
/**
|
|
3623
|
-
*
|
|
3624
|
-
* @param environment -
|
|
3625
|
-
* @param segments -
|
|
3626
|
-
*/
|
|
3627
3736
|
constructor(environment, segments) {
|
|
3628
3737
|
this.environment = environment;
|
|
3629
3738
|
this.segments = segments;
|
|
3630
3739
|
}
|
|
3631
3740
|
|
|
3632
3741
|
/**
|
|
3633
|
-
*
|
|
3634
|
-
* @param value -
|
|
3635
|
-
* @returns
|
|
3742
|
+
* Apply this JSONPath query to _value_.
|
|
3743
|
+
* @param value - A JSON-like object to apply this query to.
|
|
3744
|
+
* @returns Nodes matched by applying this query to _value_.
|
|
3636
3745
|
*/
|
|
3637
3746
|
query(value) {
|
|
3638
3747
|
let nodes = [new JSONPathNode(value, [], value)];
|
|
@@ -3643,9 +3752,9 @@ class JSONPathQuery {
|
|
|
3643
3752
|
}
|
|
3644
3753
|
|
|
3645
3754
|
/**
|
|
3646
|
-
*
|
|
3647
|
-
* @param value -
|
|
3648
|
-
* @returns
|
|
3755
|
+
* Apply this JSONPath query to _value_.
|
|
3756
|
+
* @param value - A JSON-like object to apply this query to.
|
|
3757
|
+
* @returns An iterator over nodes matched by applying this query to _value_.
|
|
3649
3758
|
*/
|
|
3650
3759
|
lazyQuery(value) {
|
|
3651
3760
|
let nodes = [new JSONPathNode(value, [], value)][Symbol.iterator]();
|
|
@@ -3671,11 +3780,15 @@ class JSONPathQuery {
|
|
|
3671
3780
|
}
|
|
3672
3781
|
|
|
3673
3782
|
/**
|
|
3674
|
-
*
|
|
3783
|
+
* Return a string representation of this query.
|
|
3675
3784
|
*/
|
|
3676
|
-
toString() {
|
|
3677
|
-
return `$${this.segments.map(s => s.toString()).join("")}`;
|
|
3785
|
+
toString(options) {
|
|
3786
|
+
return `$${this.segments.map(s => s.toString(options)).join("")}`;
|
|
3678
3787
|
}
|
|
3788
|
+
|
|
3789
|
+
/**
|
|
3790
|
+
* Return `true` if this query is a _singular query_, or `false` otherwise.
|
|
3791
|
+
*/
|
|
3679
3792
|
singularQuery() {
|
|
3680
3793
|
for (const segment of this.segments) {
|
|
3681
3794
|
if (segment instanceof DescendantSegment) return false;
|
|
@@ -3717,8 +3830,15 @@ class KeySelector extends JSONPathSelector {
|
|
|
3717
3830
|
yield new JSONPathNode(this.key, node.location.concat(`${KEY_MARK}${this.key}`), node.root);
|
|
3718
3831
|
}
|
|
3719
3832
|
}
|
|
3720
|
-
toString() {
|
|
3721
|
-
|
|
3833
|
+
toString(options) {
|
|
3834
|
+
const {
|
|
3835
|
+
form
|
|
3836
|
+
} = {
|
|
3837
|
+
...defaultSerializationOptions,
|
|
3838
|
+
...options
|
|
3839
|
+
};
|
|
3840
|
+
const serialize = form === "canonical" ? toCanonical : toQuoted;
|
|
3841
|
+
return `~${serialize(this.key)}`;
|
|
3722
3842
|
}
|
|
3723
3843
|
}
|
|
3724
3844
|
|
|
@@ -3794,8 +3914,8 @@ class KeysFilterSelector extends JSONPathSelector {
|
|
|
3794
3914
|
}
|
|
3795
3915
|
}
|
|
3796
3916
|
}
|
|
3797
|
-
toString() {
|
|
3798
|
-
return `~?${this.expression.toString()}`;
|
|
3917
|
+
toString(options) {
|
|
3918
|
+
return `~?${this.expression.toString(options)}`;
|
|
3799
3919
|
}
|
|
3800
3920
|
}
|
|
3801
3921
|
|
|
@@ -5085,6 +5205,6 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
5085
5205
|
apply: apply
|
|
5086
5206
|
});
|
|
5087
5207
|
|
|
5088
|
-
const version = "2.
|
|
5208
|
+
const version = "2.1.0";
|
|
5089
5209
|
|
|
5090
5210
|
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 };
|