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.cjs.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
|
|
@@ -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) {
|
|
@@ -3165,8 +3260,17 @@ class NameSelector extends JSONPathSelector {
|
|
|
3165
3260
|
yield new JSONPathNode(node.value[this.name], node.location.concat(this.name), node.root);
|
|
3166
3261
|
}
|
|
3167
3262
|
}
|
|
3168
|
-
toString() {
|
|
3169
|
-
|
|
3263
|
+
toString(options) {
|
|
3264
|
+
const {
|
|
3265
|
+
form
|
|
3266
|
+
} = {
|
|
3267
|
+
...defaultSerializationOptions,
|
|
3268
|
+
...options
|
|
3269
|
+
};
|
|
3270
|
+
return form === "canonical" ? toCanonical(this.name) : toQuoted(this.name);
|
|
3271
|
+
}
|
|
3272
|
+
shorthand() {
|
|
3273
|
+
return toShorthand(this.name);
|
|
3170
3274
|
}
|
|
3171
3275
|
}
|
|
3172
3276
|
|
|
@@ -3435,8 +3539,8 @@ class FilterSelector extends JSONPathSelector {
|
|
|
3435
3539
|
}
|
|
3436
3540
|
}
|
|
3437
3541
|
}
|
|
3438
|
-
toString() {
|
|
3439
|
-
return `?${this.expression.toString()}`;
|
|
3542
|
+
toString(options) {
|
|
3543
|
+
return `?${this.expression.toString(options)}`;
|
|
3440
3544
|
}
|
|
3441
3545
|
}
|
|
3442
3546
|
|
|
@@ -3467,7 +3571,7 @@ class JSONPathSegment {
|
|
|
3467
3571
|
*/
|
|
3468
3572
|
|
|
3469
3573
|
/**
|
|
3470
|
-
* Return a
|
|
3574
|
+
* Return a string representation of this segment.
|
|
3471
3575
|
*/
|
|
3472
3576
|
}
|
|
3473
3577
|
|
|
@@ -3489,8 +3593,18 @@ class ChildSegment extends JSONPathSegment {
|
|
|
3489
3593
|
}
|
|
3490
3594
|
}
|
|
3491
3595
|
}
|
|
3492
|
-
toString() {
|
|
3493
|
-
|
|
3596
|
+
toString(options) {
|
|
3597
|
+
const {
|
|
3598
|
+
form
|
|
3599
|
+
} = {
|
|
3600
|
+
...defaultSerializationOptions,
|
|
3601
|
+
...options
|
|
3602
|
+
};
|
|
3603
|
+
if (form === "pretty" && this.selectors.length === 1 && this.selectors[0] instanceof NameSelector) {
|
|
3604
|
+
const shorthand = this.selectors[0].shorthand();
|
|
3605
|
+
if (shorthand != null) return `.${shorthand}`;
|
|
3606
|
+
}
|
|
3607
|
+
return `[${this.selectors.map(s => s.toString(options)).join(", ")}]`;
|
|
3494
3608
|
}
|
|
3495
3609
|
}
|
|
3496
3610
|
|
|
@@ -3517,8 +3631,8 @@ class DescendantSegment extends JSONPathSegment {
|
|
|
3517
3631
|
}
|
|
3518
3632
|
}
|
|
3519
3633
|
}
|
|
3520
|
-
toString() {
|
|
3521
|
-
return `..[${this.selectors.map(s => s.toString()).join(", ")}]`;
|
|
3634
|
+
toString(options) {
|
|
3635
|
+
return `..[${this.selectors.map(s => s.toString(options)).join(", ")}]`;
|
|
3522
3636
|
}
|
|
3523
3637
|
visit(node) {
|
|
3524
3638
|
var _this = this;
|
|
@@ -3618,23 +3732,18 @@ function shuffle(entries) {
|
|
|
3618
3732
|
}
|
|
3619
3733
|
|
|
3620
3734
|
/**
|
|
3621
|
-
*
|
|
3735
|
+
* A compiled JSONPath query ready to be applied to different data repeatedly.
|
|
3622
3736
|
*/
|
|
3623
3737
|
class JSONPathQuery {
|
|
3624
|
-
/**
|
|
3625
|
-
*
|
|
3626
|
-
* @param environment -
|
|
3627
|
-
* @param segments -
|
|
3628
|
-
*/
|
|
3629
3738
|
constructor(environment, segments) {
|
|
3630
3739
|
this.environment = environment;
|
|
3631
3740
|
this.segments = segments;
|
|
3632
3741
|
}
|
|
3633
3742
|
|
|
3634
3743
|
/**
|
|
3635
|
-
*
|
|
3636
|
-
* @param value -
|
|
3637
|
-
* @returns
|
|
3744
|
+
* Apply this JSONPath query to _value_.
|
|
3745
|
+
* @param value - A JSON-like object to apply this query to.
|
|
3746
|
+
* @returns Nodes matched by applying this query to _value_.
|
|
3638
3747
|
*/
|
|
3639
3748
|
query(value) {
|
|
3640
3749
|
let nodes = [new JSONPathNode(value, [], value)];
|
|
@@ -3645,9 +3754,9 @@ class JSONPathQuery {
|
|
|
3645
3754
|
}
|
|
3646
3755
|
|
|
3647
3756
|
/**
|
|
3648
|
-
*
|
|
3649
|
-
* @param value -
|
|
3650
|
-
* @returns
|
|
3757
|
+
* Apply this JSONPath query to _value_.
|
|
3758
|
+
* @param value - A JSON-like object to apply this query to.
|
|
3759
|
+
* @returns An iterator over nodes matched by applying this query to _value_.
|
|
3651
3760
|
*/
|
|
3652
3761
|
lazyQuery(value) {
|
|
3653
3762
|
let nodes = [new JSONPathNode(value, [], value)][Symbol.iterator]();
|
|
@@ -3673,11 +3782,15 @@ class JSONPathQuery {
|
|
|
3673
3782
|
}
|
|
3674
3783
|
|
|
3675
3784
|
/**
|
|
3676
|
-
*
|
|
3785
|
+
* Return a string representation of this query.
|
|
3677
3786
|
*/
|
|
3678
|
-
toString() {
|
|
3679
|
-
return `$${this.segments.map(s => s.toString()).join("")}`;
|
|
3787
|
+
toString(options) {
|
|
3788
|
+
return `$${this.segments.map(s => s.toString(options)).join("")}`;
|
|
3680
3789
|
}
|
|
3790
|
+
|
|
3791
|
+
/**
|
|
3792
|
+
* Return `true` if this query is a _singular query_, or `false` otherwise.
|
|
3793
|
+
*/
|
|
3681
3794
|
singularQuery() {
|
|
3682
3795
|
for (const segment of this.segments) {
|
|
3683
3796
|
if (segment instanceof DescendantSegment) return false;
|
|
@@ -3719,8 +3832,15 @@ class KeySelector extends JSONPathSelector {
|
|
|
3719
3832
|
yield new JSONPathNode(this.key, node.location.concat(`${KEY_MARK}${this.key}`), node.root);
|
|
3720
3833
|
}
|
|
3721
3834
|
}
|
|
3722
|
-
toString() {
|
|
3723
|
-
|
|
3835
|
+
toString(options) {
|
|
3836
|
+
const {
|
|
3837
|
+
form
|
|
3838
|
+
} = {
|
|
3839
|
+
...defaultSerializationOptions,
|
|
3840
|
+
...options
|
|
3841
|
+
};
|
|
3842
|
+
const serialize = form === "canonical" ? toCanonical : toQuoted;
|
|
3843
|
+
return `~${serialize(this.key)}`;
|
|
3724
3844
|
}
|
|
3725
3845
|
}
|
|
3726
3846
|
|
|
@@ -3796,8 +3916,8 @@ class KeysFilterSelector extends JSONPathSelector {
|
|
|
3796
3916
|
}
|
|
3797
3917
|
}
|
|
3798
3918
|
}
|
|
3799
|
-
toString() {
|
|
3800
|
-
return `~?${this.expression.toString()}`;
|
|
3919
|
+
toString(options) {
|
|
3920
|
+
return `~?${this.expression.toString(options)}`;
|
|
3801
3921
|
}
|
|
3802
3922
|
}
|
|
3803
3923
|
|
|
@@ -5087,7 +5207,7 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
5087
5207
|
apply: apply
|
|
5088
5208
|
});
|
|
5089
5209
|
|
|
5090
|
-
const version = "2.
|
|
5210
|
+
const version = "2.1.0";
|
|
5091
5211
|
|
|
5092
5212
|
exports.DEFAULT_ENVIRONMENT = DEFAULT_ENVIRONMENT;
|
|
5093
5213
|
exports.FunctionExpressionType = FunctionExpressionType;
|