Skip to content

Commit

Permalink
Make sure the keys selector produces valid "normalized" paths
Browse files Browse the repository at this point in the history
  • Loading branch information
jg-rp committed Mar 25, 2024
1 parent 09d03ee commit ba048e1
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 5 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

**Features**

- Added a non-standard _keys_ selector (`~`). The keys selector selects property names from an object or indexes from and array. It is only enabled when setting the `strict` option to `false` when constructing a `JSONPathEnvironment`.
- Added a non-standard _keys_ selector (`~`). The keys selector selects property names from an object or indexes from an array. It is only enabled when setting the `strict` option to `false` when constructing a `JSONPathEnvironment`.
- Added a non-standard _current key_ identifier (`#`). `#` will be the key or index corresponding to `@` in a filter expression. The current key identifier is only enabled when setting the `strict` option to `false` when constructing a `JSONPathEnvironment`.

## Version 1.1.1
Expand Down
16 changes: 12 additions & 4 deletions src/path/extra/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ export class KeysSelector extends JSONPathSelector {
if (isArray(node.value)) {
for (let i = 0; i < node.value.length; i++) {
rv.push(
new JSONPathNode(i, node.location.concat(`~${i}`), node.root),
new JSONPathNode(i, node.location.concat(`[~][${i}]`), node.root),
);
}
} else if (isObject(node.value)) {
let i = 0;
for (const [key, _] of this.environment.entries(node.value)) {
rv.push(
new JSONPathNode(key, node.location.concat(`~${key}`), node.root),
new JSONPathNode(key, node.location.concat(`[~][${i}]`), node.root),
);
i++;
}
}
}
Expand All @@ -42,15 +44,21 @@ export class KeysSelector extends JSONPathSelector {
if (node.value instanceof String) continue;
if (isArray(node.value)) {
for (let i = 0; i < node.value.length; i++) {
yield new JSONPathNode(i, node.location.concat(`~${i}`), node.root);
yield new JSONPathNode(
i,
node.location.concat(`[~][${i}]`),
node.root,
);
}
} else if (isObject(node.value)) {
let i = 0;
for (const [key, _] of this.environment.entries(node.value)) {
yield new JSONPathNode(
key,
node.location.concat(`~${key}`),
node.location.concat(`[~][${i}]`),
node.root,
);
i++;
}
}
}
Expand Down
25 changes: 25 additions & 0 deletions tests/path/extra.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,33 @@ describe("extra features", () => {
"$description",
({ path, data, want }: TestCase) => {
expect(env.query(path, data).values()).toStrictEqual(want);
expect(
Array.from(env.lazyQuery(path, data)).map((n) => n.value),
).toStrictEqual(want);
},
);

test("keys from an array, location is valid", () => {
const path = "$.some[?# > 1]";
const data = { some: ["other", "thing", "foo", "bar"] };
const nodes = env.query(path, data);
expect(nodes.values()).toStrictEqual(["foo", "bar"]);
expect(env.query(nodes.nodes[0].path, data).values()).toStrictEqual([
"foo",
]);
expect(env.query(nodes.nodes[1].path, data).values()).toStrictEqual([
"bar",
]);
});

test("keys from an object, location is valid", () => {
const path = "$.some[?match(#, '^b.*')]";
const data = { some: { foo: "a", bar: "b", baz: "c", qux: "d" } };
const nodes = env.query(path, data);
expect(nodes.values()).toStrictEqual(["b", "c"]);
expect(env.query(nodes.nodes[0].path, data).values()).toStrictEqual(["b"]);
expect(env.query(nodes.nodes[1].path, data).values()).toStrictEqual(["c"]);
});
});

describe("extra errors", () => {
Expand Down

0 comments on commit ba048e1

Please sign in to comment.