Skip to content

Commit

Permalink
Refactor to model JSONPath segments explicitly
Browse files Browse the repository at this point in the history
  • Loading branch information
jg-rp committed Dec 9, 2024
1 parent 752ec52 commit 8010c0e
Show file tree
Hide file tree
Showing 5 changed files with 511 additions and 606 deletions.
170 changes: 78 additions & 92 deletions src/path/extra/selectors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isArray, isObject } from "../../types";
import { isArray, isObject, isString } from "../../types";
import { JSONPathEnvironment } from "../environment";
import { LogicalExpression } from "../expression";
import { JSONPathNode } from "../node";
Expand All @@ -11,45 +11,41 @@ export class KeySelector extends JSONPathSelector {
readonly environment: JSONPathEnvironment,
readonly token: Token,
readonly key: string,
readonly shorthand: boolean = false,
) {
super(environment, token);
}

public resolve(nodes: JSONPathNode[]): JSONPathNode[] {
public resolve(node: JSONPathNode): JSONPathNode[] {
const rv: JSONPathNode[] = [];
for (const node of nodes) {
if (node.value instanceof String || isArray(node.value)) continue;
if (isObject(node.value) && hasStringKey(node.value, this.key)) {
rv.push(
new JSONPathNode(
this.key,
node.location.concat(`${KEY_MARK}${this.key}`),
node.root,
),
);
}
if (node.value instanceof String || isArray(node.value)) return rv;
if (isObject(node.value) && hasStringKey(node.value, this.key)) {
rv.push(
new JSONPathNode(
this.key,
node.location.concat(`${KEY_MARK}${this.key}`),
node.root,
),
);
}
return rv;
}

public *lazyResolve(nodes: Iterable<JSONPathNode>): Generator<JSONPathNode> {
for (const node of nodes) {
if (node.value instanceof String || isArray(node.value)) continue;
if (isObject(node.value) && hasStringKey(node.value, this.key)) {
yield new JSONPathNode(
this.key,
node.location.concat(`${KEY_MARK}${this.key}`),
node.root,
);
}
public *lazyResolve(node: JSONPathNode): Generator<JSONPathNode> {
if (
!isString(node.value) &&
isObject(node.value) &&
hasStringKey(node.value, this.key)
) {
yield new JSONPathNode(
this.key,
node.location.concat(`${KEY_MARK}${this.key}`),
node.root,
);
}
}

public toString(): string {
return this.shorthand
? `[~'${this.key.replaceAll("'", "\\'")}']`
: `~'${this.key.replaceAll("'", "\\'")}'`;
return `~'${this.key.replaceAll("'", "\\'")}'`;
}
}

Expand All @@ -60,47 +56,41 @@ export class KeysSelector extends JSONPathSelector {
constructor(
readonly environment: JSONPathEnvironment,
readonly token: Token,
readonly shorthand: boolean = false,
) {
super(environment, token);
}

public resolve(nodes: JSONPathNode[]): JSONPathNode[] {
public resolve(node: JSONPathNode): JSONPathNode[] {
const rv: JSONPathNode[] = [];
for (const node of nodes) {
if (node.value instanceof String || isArray(node.value)) continue;
if (isObject(node.value)) {
for (const [key, _] of this.environment.entries(node.value)) {
rv.push(
new JSONPathNode(
key,
node.location.concat(`${KEY_MARK}${key}`),
node.root,
),
);
}
if (node.value instanceof String || isArray(node.value)) return rv;
if (isObject(node.value)) {
for (const [key, _] of this.environment.entries(node.value)) {
rv.push(
new JSONPathNode(
key,
node.location.concat(`${KEY_MARK}${key}`),
node.root,
),
);
}
}
return rv;
}

public *lazyResolve(nodes: Iterable<JSONPathNode>): Generator<JSONPathNode> {
for (const node of nodes) {
if (node.value instanceof String || isArray(node.value)) continue;
if (isObject(node.value)) {
for (const [key, _] of this.environment.entries(node.value)) {
yield new JSONPathNode(
key,
node.location.concat(`${KEY_MARK}${key}`),
node.root,
);
}
public *lazyResolve(node: JSONPathNode): Generator<JSONPathNode> {
if (isObject(node.value) && !isString(node.value) && !isArray(node.value)) {
for (const [key, _] of this.environment.entries(node.value)) {
yield new JSONPathNode(
key,
node.location.concat(`${KEY_MARK}${key}`),
node.root,
);
}
}
}

public toString(): string {
return this.shorthand ? "[~]" : "~";
return "~";
}
}

Expand All @@ -113,52 +103,48 @@ export class KeysFilterSelector extends JSONPathSelector {
super(environment, token);
}

public resolve(nodes: JSONPathNode[]): JSONPathNode[] {
public resolve(node: JSONPathNode): JSONPathNode[] {
const rv: JSONPathNode[] = [];
for (const node of nodes) {
if (node.value instanceof String || isArray(node.value)) continue;
if (isObject(node.value)) {
for (const [key, value] of this.environment.entries(node.value)) {
const filterContext: FilterContext = {
environment: this.environment,
currentValue: value,
rootValue: node.root,
currentKey: key,
};
if (this.expression.evaluate(filterContext)) {
rv.push(
new JSONPathNode(
key,
node.location.concat(`${KEY_MARK}${key}`),
node.root,
),
);
}
if (node.value instanceof String || isArray(node.value)) return rv;
if (isObject(node.value)) {
for (const [key, value] of this.environment.entries(node.value)) {
const filterContext: FilterContext = {
environment: this.environment,
currentValue: value,
rootValue: node.root,
currentKey: key,
};
if (this.expression.evaluate(filterContext)) {
rv.push(
new JSONPathNode(
key,
node.location.concat(`${KEY_MARK}${key}`),
node.root,
),
);
}
}
}
return rv;
}

public *lazyResolve(nodes: Iterable<JSONPathNode>): Generator<JSONPathNode> {
for (const node of nodes) {
if (node.value instanceof String || isArray(node.value)) continue;
if (isObject(node.value)) {
for (const [key, value] of this.environment.entries(node.value)) {
const filterContext: FilterContext = {
environment: this.environment,
currentValue: value,
rootValue: node.root,
lazy: true,
currentKey: key,
};
if (this.expression.evaluate(filterContext)) {
yield new JSONPathNode(
key,
node.location.concat(`${KEY_MARK}${key}`),
node.root,
);
}
public *lazyResolve(node: JSONPathNode): Generator<JSONPathNode> {
if (node.value instanceof String || isArray(node.value)) return;
if (isObject(node.value)) {
for (const [key, value] of this.environment.entries(node.value)) {
const filterContext: FilterContext = {
environment: this.environment,
currentValue: value,
rootValue: node.root,
lazy: true,
currentKey: key,
};
if (this.expression.evaluate(filterContext)) {
yield new JSONPathNode(
key,
node.location.concat(`${KEY_MARK}${key}`),
node.root,
);
}
}
}
Expand Down
Loading

0 comments on commit 8010c0e

Please sign in to comment.