json-mask-validator 1.0.3

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.
Files changed (3) hide show
  1. package/README.md +125 -0
  2. package/index.js +95 -0
  3. package/package.json +24 -0
package/README.md ADDED
@@ -0,0 +1,125 @@
1
+ # json-mask-validator
2
+
3
+ A lightweight, high-performance Node.js utility for validating JSON payloads against a JSON Schema and masking/filtering fields using dynamic dot-notation paths. It seamlessly supports deep nesting, structural preservation, and **dynamic array mapping traversal**.
4
+
5
+ ## Features
6
+
7
+ - 🛡️ **Schema Validation:** Built on top of `ajv` (the fastest JSON Schema validator for Node.js).
8
+ - 🔍 **Dynamic Filtering:** Mask objects to retain only explicitly requested field paths.
9
+ - 🌳 **Structure Preservation:** Keeps original parent hierarchies, nesting depths, and structures intact.
10
+ - 🔄 **Smart Array Traversal:** Automatically detects mid-path arrays and maps fields across every element inside the collection.
11
+
12
+ ---
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install json-mask-validator
18
+ ```
19
+
20
+ Make sure your project is configured for ES Modules (`"type": "module"` in your `package.json`), or use a bundler/transpiler like TypeScript/Babel.
21
+
22
+ ---
23
+
24
+ ## Usage
25
+
26
+ ### 1. Standard Nested Objects
27
+ Filter deeply nested structures without losing their shape.
28
+
29
+ ```javascript
30
+ import { maskAndValidate } from 'json-mask-validator';
31
+
32
+ const sampleData = {
33
+ a: {
34
+ b: {
35
+ c: "ddc",
36
+ d: [1, 2, 3, 4]
37
+ },
38
+ x: "fc"
39
+ }
40
+ };
41
+
42
+ const sampleSchema = {
43
+ type: "object",
44
+ properties: {
45
+ a: { type: "object" }
46
+ },
47
+ required: ["a"]
48
+ };
49
+
50
+ // Mask a deep sub-property
51
+ const res1 = maskAndValidate(sampleData, ['a.b.d'], sampleSchema);
52
+ console.log(res1);
53
+ // Output: { a: { b: { d: [1, 2, 3, 4] } } }
54
+
55
+ // Mask an intermediate parent object
56
+ const res2 = maskAndValidate(sampleData, ['a.x'], sampleSchema);
57
+ console.log(res2);
58
+ // Output: { a: { x: "fc" } }
59
+ ```
60
+
61
+ ### 2. Smart Array Traversal
62
+ If a path targets a property inside an array of objects, the package automatically iterates through the array items to extract and re-structure the target field.
63
+
64
+ ```javascript
65
+ import { maskAndValidate } from 'json-mask-validator';
66
+
67
+ const arrayData = {
68
+ a: [
69
+ { b: "scd", c: "df" },
70
+ { b: "rt", c: "gh" }
71
+ ]
72
+ };
73
+
74
+ const schema = {
75
+ type: "object",
76
+ properties: {
77
+ a: {
78
+ type: "array",
79
+ items: { type: "object" }
80
+ }
81
+ }
82
+ };
83
+
84
+ // Requesting 'a.b' automatically loops through the collection in 'a'
85
+ const result = maskAndValidate(arrayData, ['a.b'], schema);
86
+ console.log(JSON.stringify(result));
87
+ // Output: { "a": [{ "b": "scd" }, { "b": "rt" }] }
88
+ ```
89
+
90
+ ### 3. Multiple Paths Extraction
91
+ Combine multiple paths to pick and choose specific disjointed sections of the JSON tree.
92
+
93
+ ```javascript
94
+ const combined = maskAndValidate(sampleData, ['a.b.c', 'a.x'], sampleSchema);
95
+ console.log(combined);
96
+ // Output: { a: { b: { c: "ddc" }, x: "fc" } }
97
+ ```
98
+
99
+ ---
100
+
101
+ ## API Reference
102
+
103
+ ### `maskAndValidate(jsonData, paths, schema)`
104
+
105
+ Validates the input structural integrity, filters the fields, and reconstructs the mapped result object.
106
+
107
+ #### Parameters:
108
+
109
+ | Parameter | Type | Description |
110
+ | :--- | :--- | :--- |
111
+ | `jsonData` | `Object` | The input JSON object to parse and filter. |
112
+ | `paths` | `Array<string>` | An array of dot-notation string paths to preserve (e.g., `['a.b.c', 'user.profile.id']`). |
113
+ | `schema` | `Object` | A valid standard **JSON Schema** object compatible with Ajv. |
114
+
115
+ #### Returns:
116
+ - `Object`: A new object containing only the matched structure and values.
117
+
118
+ #### Throws:
119
+ - `Error`: Throws an explicit schema validation error if the incoming `jsonData` violates the rules defined in `schema`.
120
+
121
+ ---
122
+
123
+ ## License
124
+
125
+ MIT © Abhijith C U
package/index.js ADDED
@@ -0,0 +1,95 @@
1
+ import Ajv from 'ajv';
2
+
3
+ const ajv = new Ajv();
4
+
5
+ /**
6
+ * Recursively extracts data based on a path array, handling mid-path arrays gracefully.
7
+ */
8
+ function getDeepValue(source, pathArray) {
9
+ if (source === null || source === undefined) return undefined;
10
+ if (pathArray.length === 0) return source;
11
+
12
+ const [currentKey, ...remainingPath] = pathArray;
13
+
14
+ // If the current source is an array, we need to extract the path from EVERY item inside it
15
+ if (Array.isArray(source)) {
16
+ return source
17
+ .map(item => getDeepValue(item, pathArray)) // pass the same path array down to items
18
+ .filter(val => val !== undefined);
19
+ }
20
+
21
+ // If it's an object, dig deeper
22
+ if (typeof source === 'object') {
23
+ const nextValue = source[currentKey];
24
+
25
+ // If the next value is an array, we handle it sequentially
26
+ if (Array.isArray(nextValue)) {
27
+ return nextValue.map(item => getDeepValue(item, remainingPath));
28
+ }
29
+
30
+ return getDeepValue(nextValue, remainingPath);
31
+ }
32
+
33
+ return undefined;
34
+ }
35
+
36
+ /**
37
+ * Recursively builds the target object/array structure based on the path and extracted value.
38
+ */
39
+ function setDeepValue(target, pathArray, value) {
40
+ if (pathArray.length === 0 || value === undefined) return;
41
+
42
+ const [currentKey, ...remainingPath] = pathArray;
43
+
44
+ // Case 1: The value provided is an array resulting from an array-mapping traversal
45
+ if (Array.isArray(value) && remainingPath.length > 0) {
46
+ if (!target[currentKey]) {
47
+ target[currentKey] = [];
48
+ }
49
+
50
+ value.forEach((subValue, index) => {
51
+ if (!target[currentKey][index]) {
52
+ target[currentKey][index] = {};
53
+ }
54
+ setDeepValue(target[currentKey][index], remainingPath, subValue);
55
+ });
56
+ return;
57
+ }
58
+
59
+ // Case 2: Standard leaf-node assignment
60
+ if (remainingPath.length === 0) {
61
+ target[currentKey] = JSON.parse(JSON.stringify(value));
62
+ return;
63
+ }
64
+
65
+ // Case 3: Standard nested object traversal
66
+ if (!target[currentKey]) {
67
+ target[currentKey] = {};
68
+ }
69
+ setDeepValue(target[currentKey], remainingPath, value);
70
+ }
71
+
72
+ /**
73
+ * Main export function
74
+ */
75
+ export function maskAndValidate(jsonData, paths, schema) {
76
+ const validate = ajv.compile(schema);
77
+ const valid = validate(jsonData);
78
+
79
+ if (!valid) {
80
+ throw new Error(`Schema Validation Failed: ${ajv.errorsText(validate.errors)}`);
81
+ }
82
+
83
+ const result = {};
84
+
85
+ for (const path of paths) {
86
+ const pathArray = path.split('.');
87
+ const val = getDeepValue(jsonData, pathArray);
88
+
89
+ if (val !== undefined) {
90
+ setDeepValue(result, pathArray, val);
91
+ }
92
+ }
93
+
94
+ return result;
95
+ }
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "json-mask-validator",
3
+ "version": "1.0.3",
4
+ "description": "A lightweight Node.js utility to validate JSON data against a schema and extract specific fields while preserving their nested structures and automatically traversing arrays.",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "keywords": [
8
+ "json",
9
+ "mask",
10
+ "filter",
11
+ "validator",
12
+ "ajv",
13
+ "dot-notation"
14
+ ],
15
+ "files": [
16
+ "index.js",
17
+ "README.md"
18
+ ],
19
+ "author": "Abhijith C U <abhijithcucu@gmail.com>",
20
+ "license": "MIT",
21
+ "dependencies": {
22
+ "ajv": "8.12.0"
23
+ }
24
+ }