Skip to content

Commit

Permalink
TS - add jsonpatch, jsonpath and jsonpointer functions
Browse files Browse the repository at this point in the history
  • Loading branch information
elisherer committed Aug 28, 2024
1 parent e3f2fbc commit b53e98f
Show file tree
Hide file tree
Showing 10 changed files with 340 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ void multipleResults() {
{ "id": 3, "active": false },
{ "id": 4, "active": true },
{ "id": 5, "active": false }
]"""), "$$jsonpath('\\\\$[*][?(@.active == true)]'):$", fromJson("""
]"""), "$$jsonpath('\\\\$[?(@.active == true)]'):$", fromJson("""
[
{ "id": 1, "active": true },
{ "id": 4, "active": true }
Expand Down
33 changes: 33 additions & 0 deletions javascript/json-transform/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions javascript/json-transform/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,23 @@
"date-fns": "^3.6.0",
"date-fns-tz": "^3.1.3",
"fast-json-stable-stringify": "^2.1.0",
"fast-json-patch": "^3.1.1",
"json-pointer": "^0.6.2",
"jsonpath": "^1.1.1",
"uuid": "^10.0.0"
},
"devDependencies": {
"@nlighten/json-schema-utils": "^1.0.2",
"@types/json-pointer": "^1.0.34",
"@types/jsonpath": "^0.2.4",
"@types/uuid": "^10.0.0",
"@wortise/sequency": "^0.20.0",
"bignumber.js": "^9.1.2",
"date-fns": "^3.6.0",
"date-fns-tz": "^3.1.3",
"fast-json-stable-stringify": "^2.1.0",
"fast-json-patch": "^3.1.1",
"json-pointer": "^0.6.2",
"jsonpath": "^1.1.1",
"microbundle": "^0.15.1",
"prettier": "3.1.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { describe, test } from "vitest";
import { assertTransformation } from "../BaseTransformationTest";
import { BigDecimal } from "../../functions/common/FunctionHelpers";

describe("TransformerFunctionJsonPatch", () => {
test("add", async () => {
await assertTransformation(
{
a: {
b: "c",
},
},
{
$$jsonpatch: "$",
ops: [{ op: "add", path: "/a/d", value: "e" }],
},
{
a: {
b: "c",
d: "e",
},
},
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { describe, test } from "vitest";
import { assertTransformation } from "../BaseTransformationTest";
import { BigDecimal } from "../../functions/common/FunctionHelpers";

describe("TransformerFunctionJsonPath", () => {
test("yoDawg", async () => {
await assertTransformation(
{
path: "$.path",
},
"$$jsonpath($.path):$",
"$.path",
);
});

test("inArray", async () => {
await assertTransformation(
{
arr: [null, "boo"],
},
"$$jsonpath('\\\\$.arr[1]'):$",
"boo",
);
});

test("multipleResults", async () => {
await assertTransformation(
[
{ id: 1, active: true },
{ id: 3, active: false },
{ id: 4, active: true },
{ id: 5, active: false },
],
"$$jsonpath('\\\\$[?(@.active == true)]'):$",
[
{ id: 1, active: true },
{ id: 4, active: true },
],
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { describe, test } from "vitest";
import { assertTransformation } from "../BaseTransformationTest";
import { BigDecimal } from "../../functions/common/FunctionHelpers";

describe("TransformerFunctionJsonPointer", () => {
test("get", async () => {
await assertTransformation(
{
b: [
"c",
"d",
{
e: "Hello",
},
],
},
"$$jsonpointer(GET,/b/2/e):$",
"Hello",
);
});

test("getYoDawg", async () => {
await assertTransformation(
{
pointer: "/pointer",
},
"$$jsonpointer(get,$.pointer):$",
"/pointer",
);
});

test("set", async () => {
await assertTransformation(
{
b: [
"c",
"d",
{
e: "Hello",
},
],
},
"$$jsonpointer(SET,/b,'$.b[2]'):$",
{
b: {
e: "Hello",
},
},
);
});
test("remove", async () => {
await assertTransformation(
{
b: [
"c",
"d",
{
e: "Hello",
},
],
},
"$$jsonpointer(REMOVE,/b/2):$",
{
b: ["c", "d"],
},
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import JsonPatch from "fast-json-patch";
import TransformerFunction from "./common/TransformerFunction";
import { ArgType } from "./common/ArgType";
import { FunctionDescription } from "./common/FunctionDescription";
import FunctionContext from "./common/FunctionContext";

const DESCRIPTION: FunctionDescription = {
aliases: ["jsonpatch"],
inputType: ArgType.Any,
description: "",
arguments: {
ops: { type: ArgType.Array, position: 0, required: true, description: "A list of operations" },
},
outputType: ArgType.Any,
};
class TransformerFunctionJsonPatch extends TransformerFunction {
constructor() {
super(DESCRIPTION);
}

override async apply(context: FunctionContext): Promise<any> {
const source = await context.getJsonElement(null);
if (source == null) {
return null;
}
const ops = (await context.getJsonArray("ops")) ?? [];
return JsonPatch.applyPatch(source, ops, true).newDocument;
}
}

export default TransformerFunctionJsonPatch;
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import jp from "jsonpath";
import TransformerFunction from "./common/TransformerFunction";
import { ArgType } from "./common/ArgType";
import { FunctionDescription } from "./common/FunctionDescription";
import FunctionContext from "./common/FunctionContext";
import DocumentContext from "../DocumentContext";

const DESCRIPTION: FunctionDescription = {
aliases: ["jsonpath"],
inputType: ArgType.Any,
description: "",
arguments: {
path: { type: ArgType.String, position: 0, required: true, description: "JSONPath expression" },
options: {
type: ArgType.ArrayOfString,
position: 1,
defaultIsNull: true,
description:
"A list of options [by jayway](https://github.com/json-path/JsonPath?tab=readme-ov-file#tweaking-configuration)",
},
},
outputType: ArgType.Any,
};
class TransformerFunctionJsonPath extends TransformerFunction {
constructor() {
super(DESCRIPTION);
}

override async apply(context: FunctionContext): Promise<any> {
const source = await context.getJsonElement(null);
if (source == null) {
return null;
}
const path = await context.getString("path");
if (path == null) {
return null;
}

const optionsArray = await context.getJsonArray("options");
if (optionsArray != null && optionsArray.length > 0) {
const options = optionsArray.reduce(
(acc, val) => {
acc[val] = true;
return acc;
},
{} as Record<string, true>,
);

if (options.ALWAYS_RETURN_LIST) {
try {
return jp.query(source, path);
} catch (e: any) {
if (options.SUPPRESS_EXCEPTIONS) {
return [];
}
throw e;
}
}
}

return new DocumentContext(source).read(path);
}
}

export default TransformerFunctionJsonPath;
Loading

0 comments on commit b53e98f

Please sign in to comment.