@terzogenito/json-utils 1.0.8 → 1.0.10
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/README.md +431 -1
- package/index.js +467 -8
- package/package.json +39 -31
package/README.md
CHANGED
|
@@ -1 +1,431 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
This module provides various functions for reading, validating, and processing JSON files and URL content.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
```bash
|
|
8
|
+
npm install @terzogenito/json-utils
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Function List
|
|
12
|
+
|
|
13
|
+
### 1. `getData(path)`
|
|
14
|
+
```javascript
|
|
15
|
+
console.log(await app.getData('./test-data.json'));
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**Description**: Reads and returns data from a file asynchronously.
|
|
19
|
+
|
|
20
|
+
**Parameters**:
|
|
21
|
+
- `path` (String): Path to the file to be read
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
### 2. `getString(path)`
|
|
26
|
+
```javascript
|
|
27
|
+
console.log(app.getString('test-data.json'));
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Description**: Reads a file and returns its content as a string.
|
|
31
|
+
|
|
32
|
+
**Parameters**:
|
|
33
|
+
- `path` (String): Path to the file to be read
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
### 3. `getFile(path, callback)`
|
|
38
|
+
```javascript
|
|
39
|
+
app.getFile('test-data.json', data => {
|
|
40
|
+
console.log(app.isValid(data));
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Description**: Reads a file and processes the data using a callback function.
|
|
45
|
+
|
|
46
|
+
**Parameters**:
|
|
47
|
+
- `path` (String): Path to the file to be read
|
|
48
|
+
- `callback` (Function): Function to be called with the file data
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
### 4. `isValid(data)`
|
|
53
|
+
```javascript
|
|
54
|
+
app.getFile('test-data.json', data => {
|
|
55
|
+
console.log(app.isValid(data));
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Description**: Validates whether the data is valid JSON.
|
|
60
|
+
|
|
61
|
+
**Parameters**:
|
|
62
|
+
- `data` (Any): Data to be validated
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
### 5. `toString(data)`
|
|
67
|
+
```javascript
|
|
68
|
+
app.getFile('test-data.json', data => {
|
|
69
|
+
console.log(app.toString(data));
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Description**: Converts JSON data to a string.
|
|
74
|
+
|
|
75
|
+
**Parameters**:
|
|
76
|
+
- `data` (Object): JSON data to be converted
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
### 6. `readJSON(jsonString)`
|
|
81
|
+
```javascript
|
|
82
|
+
console.log(app.readJSON('{"name":"John","age":30,"isActive":true}'));
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Description**: Reads and parses a JSON string into a JavaScript object.
|
|
86
|
+
|
|
87
|
+
**Parameters**:
|
|
88
|
+
- `jsonString` (String): JSON string to be parsed
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
### 7. `isJSON(jsonString)`
|
|
93
|
+
```javascript
|
|
94
|
+
console.log(app.isJSON('{"name":"John","age":30,"isActive":true}'));
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Description**: Checks if a string is valid JSON.
|
|
98
|
+
|
|
99
|
+
**Parameters**:
|
|
100
|
+
- `jsonString` (String): String to be checked
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
### 8. `isJSONObject(obj)`
|
|
105
|
+
```javascript
|
|
106
|
+
console.log(app.isJSONObject({"name": "John","age": 30,"isActive": true}));
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Description**: Checks if an object is a valid JSON object.
|
|
110
|
+
|
|
111
|
+
**Parameters**:
|
|
112
|
+
- `obj` (Object): Object to be checked
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
### 9. `beautifyJSON(jsonString, indent)`
|
|
117
|
+
```javascript
|
|
118
|
+
console.log(app.beautifyJSON(jsonString));
|
|
119
|
+
console.log(app.beautifyJSON(jsonString, 4));
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Description**: Formats a JSON string with customizable indentation.
|
|
123
|
+
|
|
124
|
+
**Parameters**:
|
|
125
|
+
- `jsonString` (String): JSON string to be formatted
|
|
126
|
+
- `indent` (Number, optional): Number of spaces for indentation (default: 2)
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
### 10. `beautify(jsonObject)`
|
|
131
|
+
```javascript
|
|
132
|
+
console.log(app.beautify(sampleJSONObject));
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Description**: Formats a JSON object into a readable string.
|
|
136
|
+
|
|
137
|
+
**Parameters**:
|
|
138
|
+
- `jsonObject` (Object): JSON object to be formatted
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### 11. `getURL(url, callback)`
|
|
143
|
+
```javascript
|
|
144
|
+
app.getURL("https://example.com/data.txt", data => {
|
|
145
|
+
console.log(data);
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Description**: Fetches string content from a URL.
|
|
150
|
+
|
|
151
|
+
**Parameters**:
|
|
152
|
+
- `url` (String): Target URL
|
|
153
|
+
- `callback` (Function): Callback function that receives the data
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
### 12. `getJSON(url, callback)`
|
|
158
|
+
```javascript
|
|
159
|
+
app.getJSON("https://example.com/data.json", data => {
|
|
160
|
+
console.log(data);
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Description**: Fetches and parses JSON content from a URL.
|
|
165
|
+
|
|
166
|
+
**Parameters**:
|
|
167
|
+
- `url` (String): URL pointing to JSON file
|
|
168
|
+
- `callback` (Function): Callback function that receives JSON data
|
|
169
|
+
|
|
170
|
+
## Usage Examples
|
|
171
|
+
|
|
172
|
+
```javascript
|
|
173
|
+
const app = require('./index');
|
|
174
|
+
|
|
175
|
+
// Reading local file
|
|
176
|
+
const data = await app.getData('./data.json');
|
|
177
|
+
|
|
178
|
+
// Validating JSON
|
|
179
|
+
const isValid = app.isJSON('{"key": "value"}');
|
|
180
|
+
|
|
181
|
+
// Formatting JSON
|
|
182
|
+
const beautified = app.beautifyJSON('{"key":"value"}', 4);
|
|
183
|
+
|
|
184
|
+
// Fetching data from URL
|
|
185
|
+
app.getJSON("https://api.example.com/data", jsonData => {
|
|
186
|
+
console.log(jsonData);
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### 13. getAttributes(jsonObject)
|
|
191
|
+
```javascript
|
|
192
|
+
const dataJSON = app.readJSON(data);
|
|
193
|
+
const attributes = app.getAttributes(dataJSON);
|
|
194
|
+
// Output: ['name', 'age', 'isActive', 'address', 'hobbies']
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Description**: Extracts all attribute/keys from a JSON object and returns them as an array.
|
|
198
|
+
|
|
199
|
+
**Parameters**:
|
|
200
|
+
- jsonObject (Object|String): JSON object or JSON string
|
|
201
|
+
|
|
202
|
+
Returns: Array of attribute names
|
|
203
|
+
|
|
204
|
+
### 14. getMeta(jsonObject)
|
|
205
|
+
```javascript
|
|
206
|
+
const meta = app.getMeta(dataJSON);
|
|
207
|
+
// Output: {"name": "string", "age": "integer", "isActive": "boolean"}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Description**: Generates metadata showing attribute names and their data types.
|
|
211
|
+
|
|
212
|
+
**Parameters**:
|
|
213
|
+
- jsonObject (Object|String): JSON object or JSON string
|
|
214
|
+
|
|
215
|
+
Returns: Object with attribute names as keys and data types as values
|
|
216
|
+
|
|
217
|
+
Data Types Identified:
|
|
218
|
+
- string, integer, float, boolean, array, object, null, date
|
|
219
|
+
|
|
220
|
+
### 15. getMetaDetail(jsonObject)
|
|
221
|
+
```javascript
|
|
222
|
+
const metaDetail = app.getMetaDetail(dataJSON);
|
|
223
|
+
// Output: Detailed metadata including nested structures
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Description**: Generates comprehensive metadata including nested attributes, data types, paths, and structural information.
|
|
227
|
+
|
|
228
|
+
**Parameters**:
|
|
229
|
+
- jsonObject (Object|String): JSON object or JSON string
|
|
230
|
+
|
|
231
|
+
Returns: Object with detailed metadata for each attribute
|
|
232
|
+
|
|
233
|
+
Metadata Includes:
|
|
234
|
+
- type: Data type
|
|
235
|
+
- isRequired: Whether attribute exists
|
|
236
|
+
- path: Full path to attribute
|
|
237
|
+
- children: Nested attributes (for objects)
|
|
238
|
+
- length: Array length (for arrays)
|
|
239
|
+
- elementType: Type of array elements
|
|
240
|
+
|
|
241
|
+
### 16. getMetaCompact(jsonObject)
|
|
242
|
+
```javascript
|
|
243
|
+
const metaCompact = app.getMetaCompact(dataJSON);
|
|
244
|
+
// Output: Compact metadata format
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Description**: Creates a compact metadata representation showing the structure hierarchy.
|
|
248
|
+
|
|
249
|
+
**Parameters**:
|
|
250
|
+
- jsonObject (Object|String): JSON object or JSON string
|
|
251
|
+
|
|
252
|
+
Returns: Compact representation of JSON structure
|
|
253
|
+
|
|
254
|
+
Format Examples:
|
|
255
|
+
- "array[string]": Array of strings
|
|
256
|
+
- "array[object]": Array of objects
|
|
257
|
+
- Nested objects shown as nested objects
|
|
258
|
+
|
|
259
|
+
### 17. getPartial(jsonObject, attributes)
|
|
260
|
+
```javascript
|
|
261
|
+
const partial = app.getPartial(dataJSON, ["name", "age"]);
|
|
262
|
+
// Output: {"name": "John", "age": 30}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**Description**: Extracts specific attributes from a JSON object.
|
|
266
|
+
|
|
267
|
+
**Parameters**:
|
|
268
|
+
- jsonObject (Object|String): JSON object or JSON string
|
|
269
|
+
- attributes (Array|String|Object): Attributes to extract
|
|
270
|
+
|
|
271
|
+
attribute Parameter Types:
|
|
272
|
+
- Array: List of attribute names to extract
|
|
273
|
+
```javascript
|
|
274
|
+
app.getPartial(data, ["name", "age"])
|
|
275
|
+
```
|
|
276
|
+
- String: Single attribute name
|
|
277
|
+
```javascript
|
|
278
|
+
app.getPartial(data, "name")
|
|
279
|
+
```
|
|
280
|
+
- Object: Mapping of new names to original attributes
|
|
281
|
+
```javascript
|
|
282
|
+
app.getPartial(data, {"fullName": "name", "yearsOld": "age"})
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Returns: Object containing only the specified attributes
|
|
286
|
+
|
|
287
|
+
### 18. getPartialDeep(jsonObject, attributePaths)
|
|
288
|
+
```javascript
|
|
289
|
+
const deepPartial = app.getPartialDeep(dataJSON, ["name", "address.city", "hobbies.length"]);
|
|
290
|
+
// Output: {"name": "John", "city": "Jakarta", "length": 2}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
**Description**: Extracts attributes using nested paths (dot notation).
|
|
294
|
+
|
|
295
|
+
**Parameters**:
|
|
296
|
+
- jsonObject (Object|String): JSON object or JSON string
|
|
297
|
+
- attributePaths (Array|Object): Paths to extract
|
|
298
|
+
|
|
299
|
+
attributePaths Parameter Types:
|
|
300
|
+
- Array: List of dot-notated paths
|
|
301
|
+
```javascript
|
|
302
|
+
app.getPartialDeep(data, ["user.profile.name", "user.contact.email"])
|
|
303
|
+
```
|
|
304
|
+
- Object: Mapping of new names to paths
|
|
305
|
+
```javascript
|
|
306
|
+
app.getPartialDeep(data, {"userName": "user.profile.name", "userEmail": "user.contact.email"})
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Returns: Object with extracted values (uses last path segment as key for array input)
|
|
310
|
+
|
|
311
|
+
### 19. getPartialWithDefaults(jsonObject, attributesConfig)
|
|
312
|
+
```javascript
|
|
313
|
+
const partialWithDefaults = app.getPartialWithDefaults(dataJSON, {
|
|
314
|
+
"name": "name",
|
|
315
|
+
"status": {
|
|
316
|
+
path: "isActive",
|
|
317
|
+
transform: (val) => val ? "Active" : "Inactive"
|
|
318
|
+
},
|
|
319
|
+
"email": {
|
|
320
|
+
path: "contact.email",
|
|
321
|
+
default: "no-email@example.com"
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
**Description**: Extracts attributes with advanced configuration including default values and transformations.
|
|
327
|
+
|
|
328
|
+
**Parameters**:
|
|
329
|
+
- jsonObject (Object|String): JSON object or JSON string
|
|
330
|
+
- attributesConfig (Object): Configuration object
|
|
331
|
+
|
|
332
|
+
Configuration Options:
|
|
333
|
+
- String: Simple path extraction
|
|
334
|
+
```javascript
|
|
335
|
+
"name": "user.fullName"
|
|
336
|
+
```
|
|
337
|
+
- Object: Advanced configuration
|
|
338
|
+
```javascript
|
|
339
|
+
"formattedAge": {
|
|
340
|
+
path: "age", // Required: Path to attribute
|
|
341
|
+
default: 0, // Optional: Default value if path doesn't exist
|
|
342
|
+
transform: (val) => ${val} years old // Optional: Transformation function
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Returns: Object with extracted and processed values
|
|
347
|
+
|
|
348
|
+
### 20. excludeAttributes(jsonObject, attributesToExclude)
|
|
349
|
+
```javascript
|
|
350
|
+
const filtered = app.excludeAttributes(dataJSON, ["isActive", "address"]);
|
|
351
|
+
// Output: {"name": "John", "age": 30, "hobbies": ["reading", "coding"]}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
**Description**: Creates a new JSON object excluding specified attributes.
|
|
355
|
+
|
|
356
|
+
**Parameters**:
|
|
357
|
+
- jsonObject (Object|String): JSON object or JSON string
|
|
358
|
+
- attributesToExclude (Array|String): Attributes to remove
|
|
359
|
+
|
|
360
|
+
attributesToExclude Parameter Types:
|
|
361
|
+
- Array: List of attribute names to exclude
|
|
362
|
+
```javascript
|
|
363
|
+
app.excludeAttributes(data, ["password", "secretKey"])
|
|
364
|
+
```
|
|
365
|
+
- String: Single attribute name to exclude
|
|
366
|
+
```javascript
|
|
367
|
+
app.excludeAttributes(data, "password")
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
Returns: New object without the excluded attributes
|
|
371
|
+
|
|
372
|
+
### 21. getAttributeValue(jsonObject, attributeName, defaultValue)
|
|
373
|
+
```javascript
|
|
374
|
+
const name = app.getAttributeValue(dataJSON, "name");
|
|
375
|
+
const email = app.getAttributeValue(dataJSON, "email", "default@email.com");
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
**Description**: Gets the value of a specific attribute with optional default value.
|
|
379
|
+
|
|
380
|
+
**Parameters**:
|
|
381
|
+
- jsonObject (Object|String): JSON object or JSON string
|
|
382
|
+
- attributeName (String): Name of the attribute to retrieve
|
|
383
|
+
- defaultValue (Any, optional): Default value if attribute doesn't exist
|
|
384
|
+
|
|
385
|
+
Returns: Attribute value or default value
|
|
386
|
+
|
|
387
|
+
Advanced Usage Examples
|
|
388
|
+
```javascript
|
|
389
|
+
const app = require('./index');
|
|
390
|
+
|
|
391
|
+
// Get all attributes from JSON
|
|
392
|
+
const data = await app.getData('./data.json');
|
|
393
|
+
const jsonData = app.readJSON(data);
|
|
394
|
+
const attributes = app.getAttributes(jsonData);
|
|
395
|
+
|
|
396
|
+
// Get metadata information
|
|
397
|
+
const meta = app.getMeta(jsonData);
|
|
398
|
+
const metaDetail = app.getMetaDetail(jsonData);
|
|
399
|
+
|
|
400
|
+
// Extract specific data
|
|
401
|
+
const userInfo = app.getPartial(jsonData, ["name", "email", "phone"]);
|
|
402
|
+
const nestedData = app.getPartialDeep(jsonData, ["user.profile.name", "user.contact.email"]);
|
|
403
|
+
|
|
404
|
+
// Extract with transformations and defaults
|
|
405
|
+
const processedData = app.getPartialWithDefaults(jsonData, {
|
|
406
|
+
"fullName": "user.name",
|
|
407
|
+
"ageFormatted": {
|
|
408
|
+
path: "user.age",
|
|
409
|
+
transform: (age) => ${age} years old
|
|
410
|
+
},
|
|
411
|
+
"country": {
|
|
412
|
+
path: "user.address.country",
|
|
413
|
+
default: "Unknown"
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
// Exclude sensitive information
|
|
418
|
+
const safeData = app.excludeAttributes(jsonData, ["password", "ssn", "creditCard"]);
|
|
419
|
+
|
|
420
|
+
// Analyze complex nested structures
|
|
421
|
+
const complexMeta = app.getMetaDetail(complexJSON);
|
|
422
|
+
console.log(complexMeta.user?.children?.contact?.children?.email?.type); // "string"
|
|
423
|
+
|
|
424
|
+
// Get single attribute value
|
|
425
|
+
const userName = app.getAttributeValue(jsonData, "name");
|
|
426
|
+
const userEmail = app.getAttributeValue(jsonData, "email", "no-email@example.com");
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
## Requirements
|
|
430
|
+
- Node.js 12 or higher
|
|
431
|
+
- Internet connection (for URL functions)
|
package/index.js
CHANGED
|
@@ -1,4 +1,67 @@
|
|
|
1
|
-
const
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const https = require('https');
|
|
3
|
+
|
|
4
|
+
function getString(filePath) {
|
|
5
|
+
return fs.readFileSync(filePath, 'utf-8');
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function getFile(filePath, callback) {
|
|
9
|
+
fs.readFile(filePath, 'utf8', (err, data) => {
|
|
10
|
+
if (err) {
|
|
11
|
+
return;
|
|
12
|
+
} else {
|
|
13
|
+
callback(data);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function loadFile(filePath) {
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
fs.readFile(filePath, 'utf8', (err, data) => {
|
|
21
|
+
if (err) {
|
|
22
|
+
reject(err);
|
|
23
|
+
} else {
|
|
24
|
+
resolve(data);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function getData(filePath) {
|
|
31
|
+
try {
|
|
32
|
+
const data = await loadFile(filePath);
|
|
33
|
+
return data;
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getURL(url, callback) {
|
|
40
|
+
https.get(url, (response) => {
|
|
41
|
+
let data = '';
|
|
42
|
+
response.on('data', chunk => {
|
|
43
|
+
data += chunk;
|
|
44
|
+
});
|
|
45
|
+
response.on('end', () => {
|
|
46
|
+
callback(data || null);
|
|
47
|
+
});
|
|
48
|
+
}).on('error', (err) => {
|
|
49
|
+
callback(null);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function isUrl(input) {
|
|
54
|
+
const urlPattern = /^(https?:\/\/|ftp:\/\/|www\.)/i;
|
|
55
|
+
return urlPattern.test(input);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function getContent(target, callback) {
|
|
59
|
+
if (isUrl(target)) {
|
|
60
|
+
getURL(target, callback);
|
|
61
|
+
} else {
|
|
62
|
+
getFile(target, callback);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
2
65
|
|
|
3
66
|
function readJSON(jsonString) {
|
|
4
67
|
return JSON.parse(jsonString);
|
|
@@ -12,8 +75,7 @@ function isValid(jsonString) {
|
|
|
12
75
|
try {
|
|
13
76
|
JSON.parse(jsonString);
|
|
14
77
|
return true;
|
|
15
|
-
} catch
|
|
16
|
-
console.log("The string is not valid JSON.");
|
|
78
|
+
} catch {
|
|
17
79
|
return false;
|
|
18
80
|
}
|
|
19
81
|
}
|
|
@@ -27,30 +89,427 @@ function isJSON(jsonObject) {
|
|
|
27
89
|
}
|
|
28
90
|
}
|
|
29
91
|
|
|
92
|
+
function isJSONObject(jsonObject) {
|
|
93
|
+
try {
|
|
94
|
+
return typeof jsonObject === 'object' && jsonObject !== null && jsonObject !== undefined;
|
|
95
|
+
} catch (error) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
30
100
|
function getJSON(target, callback) {
|
|
31
|
-
|
|
32
|
-
if (
|
|
101
|
+
getContent(target, data => {
|
|
102
|
+
if (!data) {
|
|
103
|
+
return callback(null);
|
|
104
|
+
}
|
|
105
|
+
if (!isValid(data)) {
|
|
106
|
+
return callback(null);
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
33
109
|
callback(readJSON(data));
|
|
110
|
+
} catch {
|
|
111
|
+
callback(null);
|
|
34
112
|
}
|
|
35
113
|
});
|
|
36
114
|
}
|
|
37
115
|
|
|
38
|
-
function beautifyJSON(jsonString, indent) {
|
|
116
|
+
function beautifyJSON(jsonString, indent = 2) {
|
|
39
117
|
try {
|
|
118
|
+
if (typeof jsonString !== 'string') return null;
|
|
40
119
|
const jsonObject = JSON.parse(jsonString);
|
|
120
|
+
return JSON.stringify(jsonObject, null, indent);
|
|
121
|
+
} catch {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function beautify(jsonObject, indent) {
|
|
127
|
+
try {
|
|
41
128
|
if (!indent) indent = 2;
|
|
42
129
|
return JSON.stringify(jsonObject, null, indent);
|
|
43
130
|
} catch (error) {
|
|
44
|
-
console.error("Invalid JSON string:", error);
|
|
45
131
|
return null;
|
|
46
132
|
}
|
|
47
133
|
}
|
|
48
134
|
|
|
135
|
+
function getAttributes(jsonObject) {
|
|
136
|
+
try {
|
|
137
|
+
if (typeof jsonObject === 'string') {
|
|
138
|
+
jsonObject = JSON.parse(jsonObject);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (typeof jsonObject !== 'object' || jsonObject === null) {
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return Object.keys(jsonObject);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function getMeta(jsonObject) {
|
|
152
|
+
try {
|
|
153
|
+
if (typeof jsonObject === 'string') {
|
|
154
|
+
jsonObject = JSON.parse(jsonObject);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (typeof jsonObject !== 'object' || jsonObject === null) {
|
|
158
|
+
return {};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const meta = {};
|
|
162
|
+
|
|
163
|
+
for (const [key, value] of Object.entries(jsonObject)) {
|
|
164
|
+
let type = typeof value;
|
|
165
|
+
|
|
166
|
+
if (type === 'object') {
|
|
167
|
+
if (value === null) {
|
|
168
|
+
type = 'null';
|
|
169
|
+
} else if (Array.isArray(value)) {
|
|
170
|
+
type = 'array';
|
|
171
|
+
} else if (value instanceof Date) {
|
|
172
|
+
type = 'date';
|
|
173
|
+
} else {
|
|
174
|
+
type = 'object';
|
|
175
|
+
}
|
|
176
|
+
} else if (type === 'number') {
|
|
177
|
+
type = Number.isInteger(value) ? 'integer' : 'float';
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
meta[key] = type;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return meta;
|
|
184
|
+
} catch (error) {
|
|
185
|
+
return {};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function getMetaDetail(jsonObject) {
|
|
190
|
+
try {
|
|
191
|
+
if (typeof jsonObject === 'string') {
|
|
192
|
+
jsonObject = JSON.parse(jsonObject);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (typeof jsonObject !== 'object' || jsonObject === null) {
|
|
196
|
+
return {};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function getNestedMeta(obj, path = '') {
|
|
200
|
+
const meta = {};
|
|
201
|
+
|
|
202
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
203
|
+
const currentPath = path ? `${path}.${key}` : key;
|
|
204
|
+
const attributeMeta = {};
|
|
205
|
+
|
|
206
|
+
let type = typeof value;
|
|
207
|
+
|
|
208
|
+
if (value === null) {
|
|
209
|
+
type = 'null';
|
|
210
|
+
attributeMeta.type = type;
|
|
211
|
+
attributeMeta.isRequired = false;
|
|
212
|
+
attributeMeta.path = currentPath;
|
|
213
|
+
} else if (Array.isArray(value)) {
|
|
214
|
+
type = 'array';
|
|
215
|
+
attributeMeta.type = type;
|
|
216
|
+
attributeMeta.length = value.length;
|
|
217
|
+
attributeMeta.isRequired = true;
|
|
218
|
+
attributeMeta.path = currentPath;
|
|
219
|
+
|
|
220
|
+
if (value.length > 0) {
|
|
221
|
+
const firstElement = value[0];
|
|
222
|
+
const elementType = typeof firstElement;
|
|
223
|
+
|
|
224
|
+
if (elementType === 'object' && firstElement !== null) {
|
|
225
|
+
if (Array.isArray(firstElement)) {
|
|
226
|
+
attributeMeta.elementType = 'array';
|
|
227
|
+
} else {
|
|
228
|
+
attributeMeta.elementType = 'object';
|
|
229
|
+
attributeMeta.children = getNestedMeta(firstElement, `${currentPath}[0]`);
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
attributeMeta.elementType = elementType;
|
|
233
|
+
}
|
|
234
|
+
} else {
|
|
235
|
+
attributeMeta.elementType = 'unknown';
|
|
236
|
+
}
|
|
237
|
+
} else if (value instanceof Date) {
|
|
238
|
+
type = 'date';
|
|
239
|
+
attributeMeta.type = type;
|
|
240
|
+
attributeMeta.isRequired = true;
|
|
241
|
+
attributeMeta.path = currentPath;
|
|
242
|
+
} else if (type === 'object') {
|
|
243
|
+
type = 'object';
|
|
244
|
+
attributeMeta.type = type;
|
|
245
|
+
attributeMeta.isRequired = true;
|
|
246
|
+
attributeMeta.path = currentPath;
|
|
247
|
+
attributeMeta.keysCount = Object.keys(value).length;
|
|
248
|
+
|
|
249
|
+
attributeMeta.children = getNestedMeta(value, currentPath);
|
|
250
|
+
} else {
|
|
251
|
+
attributeMeta.type = type;
|
|
252
|
+
attributeMeta.isRequired = true;
|
|
253
|
+
attributeMeta.path = currentPath;
|
|
254
|
+
|
|
255
|
+
if (type === 'number') {
|
|
256
|
+
attributeMeta.numberType = Number.isInteger(value) ? 'integer' : 'float';
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
meta[key] = attributeMeta;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return meta;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return getNestedMeta(jsonObject);
|
|
267
|
+
} catch (error) {
|
|
268
|
+
console.error('Error in getMetaDetail:', error);
|
|
269
|
+
return {};
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function getMetaCompact(jsonObject) {
|
|
274
|
+
try {
|
|
275
|
+
if (typeof jsonObject === 'string') {
|
|
276
|
+
jsonObject = JSON.parse(jsonObject);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (typeof jsonObject !== 'object' || jsonObject === null) {
|
|
280
|
+
return {};
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function getCompactMeta(obj) {
|
|
284
|
+
const meta = {};
|
|
285
|
+
|
|
286
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
287
|
+
let type = typeof value;
|
|
288
|
+
|
|
289
|
+
if (value === null) {
|
|
290
|
+
meta[key] = 'null';
|
|
291
|
+
} else if (Array.isArray(value)) {
|
|
292
|
+
if (value.length > 0) {
|
|
293
|
+
const firstElement = value[0];
|
|
294
|
+
const elementType = typeof firstElement;
|
|
295
|
+
if (elementType === 'object' && firstElement !== null) {
|
|
296
|
+
meta[key] = `array[${Array.isArray(firstElement) ? 'array' : 'object'}]`;
|
|
297
|
+
} else {
|
|
298
|
+
meta[key] = `array[${elementType}]`;
|
|
299
|
+
}
|
|
300
|
+
} else {
|
|
301
|
+
meta[key] = 'array[]';
|
|
302
|
+
}
|
|
303
|
+
} else if (value instanceof Date) {
|
|
304
|
+
meta[key] = 'date';
|
|
305
|
+
} else if (type === 'object') {
|
|
306
|
+
meta[key] = getCompactMeta(value);
|
|
307
|
+
} else if (type === 'number') {
|
|
308
|
+
meta[key] = Number.isInteger(value) ? 'integer' : 'float';
|
|
309
|
+
} else {
|
|
310
|
+
meta[key] = type;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return meta;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return getCompactMeta(jsonObject);
|
|
318
|
+
} catch (error) {
|
|
319
|
+
console.error('Error in getMetaCompact:', error);
|
|
320
|
+
return {};
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function getPartial(jsonObject, attributes) {
|
|
325
|
+
try {
|
|
326
|
+
if (typeof jsonObject === 'string') {
|
|
327
|
+
jsonObject = JSON.parse(jsonObject);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (typeof jsonObject !== 'object' || jsonObject === null) {
|
|
331
|
+
return {};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const result = {};
|
|
335
|
+
|
|
336
|
+
if (Array.isArray(attributes)) {
|
|
337
|
+
for (const attr of attributes) {
|
|
338
|
+
if (attr in jsonObject) {
|
|
339
|
+
result[attr] = jsonObject[attr];
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
else if (typeof attributes === 'string') {
|
|
344
|
+
if (attributes in jsonObject) {
|
|
345
|
+
result[attributes] = jsonObject[attributes];
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
else if (typeof attributes === 'object' && attributes !== null) {
|
|
349
|
+
for (const [newKey, originalKey] of Object.entries(attributes)) {
|
|
350
|
+
if (originalKey in jsonObject) {
|
|
351
|
+
result[newKey] = jsonObject[originalKey];
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return result;
|
|
357
|
+
} catch (error) {
|
|
358
|
+
console.error('Error in getPartial:', error);
|
|
359
|
+
return {};
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function getPartialDeep(jsonObject, attributePaths) {
|
|
364
|
+
try {
|
|
365
|
+
if (typeof jsonObject === 'string') {
|
|
366
|
+
jsonObject = JSON.parse(jsonObject);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
if (typeof jsonObject !== 'object' || jsonObject === null) {
|
|
370
|
+
return {};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const result = {};
|
|
374
|
+
|
|
375
|
+
function getValueFromPath(obj, path) {
|
|
376
|
+
const parts = path.split('.');
|
|
377
|
+
let current = obj;
|
|
378
|
+
|
|
379
|
+
for (const part of parts) {
|
|
380
|
+
if (current && typeof current === 'object' && part in current) {
|
|
381
|
+
current = current[part];
|
|
382
|
+
} else {
|
|
383
|
+
return undefined;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return current;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (Array.isArray(attributePaths)) {
|
|
391
|
+
for (const path of attributePaths) {
|
|
392
|
+
const value = getValueFromPath(jsonObject, path);
|
|
393
|
+
if (value !== undefined) {
|
|
394
|
+
const key = path.split('.').pop();
|
|
395
|
+
result[key] = value;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
else if (typeof attributePaths === 'object' && attributePaths !== null) {
|
|
400
|
+
for (const [newKey, path] of Object.entries(attributePaths)) {
|
|
401
|
+
const value = getValueFromPath(jsonObject, path);
|
|
402
|
+
if (value !== undefined) {
|
|
403
|
+
result[newKey] = value;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
return result;
|
|
409
|
+
} catch (error) {
|
|
410
|
+
console.error('Error in getPartialDeep:', error);
|
|
411
|
+
return {};
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function getPartialWithDefaults(jsonObject, attributesConfig) {
|
|
416
|
+
try {
|
|
417
|
+
if (typeof jsonObject === 'string') {
|
|
418
|
+
jsonObject = JSON.parse(jsonObject);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (typeof jsonObject !== 'object' || jsonObject === null) {
|
|
422
|
+
return {};
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
const result = {};
|
|
426
|
+
|
|
427
|
+
function getValueFromPath(obj, path, defaultValue) {
|
|
428
|
+
const parts = path.split('.');
|
|
429
|
+
let current = obj;
|
|
430
|
+
|
|
431
|
+
for (const part of parts) {
|
|
432
|
+
if (current && typeof current === 'object' && part in current) {
|
|
433
|
+
current = current[part];
|
|
434
|
+
} else {
|
|
435
|
+
return defaultValue;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
return current;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
for (const [outputKey, config] of Object.entries(attributesConfig)) {
|
|
443
|
+
if (typeof config === 'string') {
|
|
444
|
+
result[outputKey] = getValueFromPath(jsonObject, config, undefined);
|
|
445
|
+
} else if (typeof config === 'object' && config !== null) {
|
|
446
|
+
const path = config.path || outputKey;
|
|
447
|
+
const defaultValue = config.default;
|
|
448
|
+
let value = getValueFromPath(jsonObject, path, defaultValue);
|
|
449
|
+
|
|
450
|
+
if (config.transform && typeof config.transform === 'function') {
|
|
451
|
+
value = config.transform(value);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
result[outputKey] = value;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
return result;
|
|
459
|
+
} catch (error) {
|
|
460
|
+
console.error('Error in getPartialWithDefaults:', error);
|
|
461
|
+
return {};
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function excludeAttributes(jsonObject, attributesToExclude) {
|
|
466
|
+
try {
|
|
467
|
+
if (typeof jsonObject === 'string') {
|
|
468
|
+
jsonObject = JSON.parse(jsonObject);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (typeof jsonObject !== 'object' || jsonObject === null) {
|
|
472
|
+
return {};
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const result = { ...jsonObject };
|
|
476
|
+
|
|
477
|
+
if (Array.isArray(attributesToExclude)) {
|
|
478
|
+
for (const attr of attributesToExclude) {
|
|
479
|
+
delete result[attr];
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
else if (typeof attributesToExclude === 'string') {
|
|
483
|
+
delete result[attributesToExclude];
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
return result;
|
|
487
|
+
} catch (error) {
|
|
488
|
+
console.error('Error in excludeAttributes:', error);
|
|
489
|
+
return {};
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
49
493
|
module.exports = {
|
|
494
|
+
getString,
|
|
495
|
+
getFile,
|
|
496
|
+
getData,
|
|
497
|
+
getURL,
|
|
498
|
+
getContent,
|
|
50
499
|
readJSON,
|
|
51
500
|
toString,
|
|
52
501
|
isValid,
|
|
53
502
|
isJSON,
|
|
503
|
+
isJSONObject,
|
|
54
504
|
getJSON,
|
|
55
505
|
beautifyJSON,
|
|
56
|
-
|
|
506
|
+
beautify,
|
|
507
|
+
getAttributes,
|
|
508
|
+
getMeta,
|
|
509
|
+
getMetaDetail,
|
|
510
|
+
getMetaCompact,
|
|
511
|
+
getPartial,
|
|
512
|
+
getPartialDeep,
|
|
513
|
+
getPartialWithDefaults,
|
|
514
|
+
excludeAttributes,
|
|
515
|
+
};
|
package/package.json
CHANGED
|
@@ -1,31 +1,39 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@terzogenito/json-utils",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"files": [
|
|
7
|
-
"index.js"
|
|
8
|
-
],
|
|
9
|
-
"scripts": {
|
|
10
|
-
"start": "node test.js",
|
|
11
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
-
},
|
|
13
|
-
"publishConfig": {
|
|
14
|
-
"access": "public"
|
|
15
|
-
},
|
|
16
|
-
"engines": {
|
|
17
|
-
"node": ">=21.6.1"
|
|
18
|
-
},
|
|
19
|
-
"keywords": [
|
|
20
|
-
"nodejs",
|
|
21
|
-
"module",
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@terzogenito/json-utils",
|
|
3
|
+
"version": "1.0.10",
|
|
4
|
+
"description": "JSON data utilities",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"index.js"
|
|
8
|
+
],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node test.js",
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
+
},
|
|
13
|
+
"publishConfig": {
|
|
14
|
+
"access": "public"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=21.6.1"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"nodejs",
|
|
21
|
+
"module",
|
|
22
|
+
"utils",
|
|
23
|
+
"tools",
|
|
24
|
+
"json",
|
|
25
|
+
"check",
|
|
26
|
+
"beautify",
|
|
27
|
+
"analysis"
|
|
28
|
+
],
|
|
29
|
+
"author": "Terzogenito",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/terzogenito/json-utils.git"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/terzogenito/json-utils#readme",
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/terzogenito/json-utils/issues"
|
|
38
|
+
}
|
|
39
|
+
}
|