@tamtamchik/json-deep-sort 1.1.4 → 1.2.1
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 +38 -13
- package/dist/index.js +14 -25
- package/dist/index.mjs +14 -25
- package/package.json +4 -4
- package/src/index.ts +32 -55
package/README.md
CHANGED
|
@@ -8,9 +8,15 @@
|
|
|
8
8
|
[![Software License][ico-license]](LICENSE)
|
|
9
9
|
[![Total Downloads][ico-downloads]][link-downloads]
|
|
10
10
|
|
|
11
|
-
JSON Deep Sort is a
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
JSON Deep Sort is a powerful and versatile TypeScript package designed for efficient sorting of JSON objects by keys. It offers:
|
|
12
|
+
|
|
13
|
+
- Comprehensive handling of deeply nested objects and arrays
|
|
14
|
+
- Flexible sorting options, including ascending and descending order
|
|
15
|
+
- Support for both synchronous and asynchronous operations
|
|
16
|
+
- Preservation of non-sortable objects (e.g., Date, RegExp, Function)
|
|
17
|
+
- Lightweight implementation with zero dependencies
|
|
18
|
+
|
|
19
|
+
Whether you're working with simple flat objects or complex nested structures, JSON Deep Sort provides a reliable solution for organizing your data.
|
|
14
20
|
|
|
15
21
|
## Installation
|
|
16
22
|
|
|
@@ -37,19 +43,38 @@ import { sort } from '@tamtamchik/json-deep-sort';
|
|
|
37
43
|
Here is an example of sorting a JSON object:
|
|
38
44
|
|
|
39
45
|
```typescript
|
|
40
|
-
|
|
46
|
+
// Example 1: Sorting a simple object
|
|
47
|
+
const simpleData = { b: 'b', a: 'a', c: 'c' };
|
|
48
|
+
console.log(sort(simpleData));
|
|
49
|
+
// Output: { a: 'a', b: 'b', c: 'c' }
|
|
50
|
+
|
|
51
|
+
// Example 2: Sorting a nested object
|
|
52
|
+
const nestedData = {
|
|
41
53
|
b: 'b',
|
|
42
54
|
a: 'a',
|
|
43
|
-
c: {
|
|
44
|
-
d: 'd',
|
|
45
|
-
c: 'c',
|
|
46
|
-
a: 'a',
|
|
47
|
-
b: 'b'
|
|
48
|
-
}
|
|
55
|
+
c: { d: 'd', c: 'c', a: 'a', b: 'b' }
|
|
49
56
|
};
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
console.log(sort(nestedData));
|
|
58
|
+
// Output: { a: 'a', b: 'b', c: { a: 'a', b: 'b', c: 'c', d: 'd' } }
|
|
59
|
+
|
|
60
|
+
// Example 3: Sorting an array of objects
|
|
61
|
+
const arrayData = [{ b: 'b', a: 'a' }, { d: 'd', c: 'c' }];
|
|
62
|
+
console.log(sort(arrayData));
|
|
63
|
+
// Output: [{ a: 'a', b: 'b' }, { c: 'c', d: 'd' }]
|
|
64
|
+
|
|
65
|
+
// Example 4: Sorting in descending order
|
|
66
|
+
const descendingData = { a: 'a', c: 'c', b: 'b' };
|
|
67
|
+
console.log(sort(descendingData, false));
|
|
68
|
+
// Output: { c: 'c', b: 'b', a: 'a' }
|
|
69
|
+
|
|
70
|
+
// Example 5: Handling mixed data types
|
|
71
|
+
const mixedData = {
|
|
72
|
+
b: [3, 1, 2],
|
|
73
|
+
a: { z: 'z', y: 'y' },
|
|
74
|
+
c: new Date('2023-01-01')
|
|
75
|
+
};
|
|
76
|
+
console.log(sort(mixedData));
|
|
77
|
+
// Output: { a: { y: 'y', z: 'z' }, b: [3, 1, 2], c: Date('2023-01-01') }
|
|
53
78
|
```
|
|
54
79
|
|
|
55
80
|
## Contributing
|
package/dist/index.js
CHANGED
|
@@ -23,34 +23,23 @@ __export(src_exports, {
|
|
|
23
23
|
sort: () => sort
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(src_exports);
|
|
26
|
-
function
|
|
26
|
+
function sort(data, asc = true) {
|
|
27
|
+
if (!data || typeof data !== "object") {
|
|
28
|
+
return data;
|
|
29
|
+
}
|
|
27
30
|
if (Array.isArray(data)) {
|
|
28
|
-
return
|
|
29
|
-
} else if (typeof data === "object" && data !== null) {
|
|
30
|
-
return 0 /* OBJECT */;
|
|
31
|
-
} else if (typeof data === "string") {
|
|
32
|
-
return 2 /* STRING */;
|
|
33
|
-
} else {
|
|
34
|
-
return 3 /* OTHER */;
|
|
31
|
+
return data.map((item) => sort(item, asc));
|
|
35
32
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return [0 /* OBJECT */, 1 /* ARRAY */].includes(getType(data));
|
|
39
|
-
}
|
|
40
|
-
function sort(data, asc = true) {
|
|
41
|
-
switch (getType(data)) {
|
|
42
|
-
case 1 /* ARRAY */:
|
|
43
|
-
return data.map((d) => isRecursiveType(d) ? sort(d, asc) : d);
|
|
44
|
-
case 0 /* OBJECT */:
|
|
45
|
-
const keys = Object.keys(data).sort();
|
|
46
|
-
if (!asc) keys.reverse();
|
|
47
|
-
return keys.reduce((newData, key) => {
|
|
48
|
-
newData[key] = isRecursiveType(data[key]) ? sort(data[key], asc) : data[key];
|
|
49
|
-
return newData;
|
|
50
|
-
}, {});
|
|
51
|
-
default:
|
|
52
|
-
throw new Error("Invalid data type: expected an object or array of objects.");
|
|
33
|
+
if (isNonSortableObject(data)) {
|
|
34
|
+
return data;
|
|
53
35
|
}
|
|
36
|
+
const sortedEntries = Object.entries(data).sort(([a], [b]) => asc ? a.localeCompare(b) : b.localeCompare(a));
|
|
37
|
+
return Object.fromEntries(
|
|
38
|
+
sortedEntries.map(([key, value]) => [key, sort(value, asc)])
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
function isNonSortableObject(obj) {
|
|
42
|
+
return obj instanceof Date || obj instanceof RegExp || obj instanceof Function || obj instanceof Error || obj instanceof Map || obj instanceof Set || obj instanceof WeakMap || obj instanceof WeakSet || obj instanceof Promise || Symbol.iterator in Object(obj);
|
|
54
43
|
}
|
|
55
44
|
// Annotate the CommonJS export names for ESM import in node:
|
|
56
45
|
0 && (module.exports = {
|
package/dist/index.mjs
CHANGED
|
@@ -1,32 +1,21 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
function
|
|
2
|
+
function sort(data, asc = true) {
|
|
3
|
+
if (!data || typeof data !== "object") {
|
|
4
|
+
return data;
|
|
5
|
+
}
|
|
3
6
|
if (Array.isArray(data)) {
|
|
4
|
-
return
|
|
5
|
-
} else if (typeof data === "object" && data !== null) {
|
|
6
|
-
return 0 /* OBJECT */;
|
|
7
|
-
} else if (typeof data === "string") {
|
|
8
|
-
return 2 /* STRING */;
|
|
9
|
-
} else {
|
|
10
|
-
return 3 /* OTHER */;
|
|
7
|
+
return data.map((item) => sort(item, asc));
|
|
11
8
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return [0 /* OBJECT */, 1 /* ARRAY */].includes(getType(data));
|
|
15
|
-
}
|
|
16
|
-
function sort(data, asc = true) {
|
|
17
|
-
switch (getType(data)) {
|
|
18
|
-
case 1 /* ARRAY */:
|
|
19
|
-
return data.map((d) => isRecursiveType(d) ? sort(d, asc) : d);
|
|
20
|
-
case 0 /* OBJECT */:
|
|
21
|
-
const keys = Object.keys(data).sort();
|
|
22
|
-
if (!asc) keys.reverse();
|
|
23
|
-
return keys.reduce((newData, key) => {
|
|
24
|
-
newData[key] = isRecursiveType(data[key]) ? sort(data[key], asc) : data[key];
|
|
25
|
-
return newData;
|
|
26
|
-
}, {});
|
|
27
|
-
default:
|
|
28
|
-
throw new Error("Invalid data type: expected an object or array of objects.");
|
|
9
|
+
if (isNonSortableObject(data)) {
|
|
10
|
+
return data;
|
|
29
11
|
}
|
|
12
|
+
const sortedEntries = Object.entries(data).sort(([a], [b]) => asc ? a.localeCompare(b) : b.localeCompare(a));
|
|
13
|
+
return Object.fromEntries(
|
|
14
|
+
sortedEntries.map(([key, value]) => [key, sort(value, asc)])
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
function isNonSortableObject(obj) {
|
|
18
|
+
return obj instanceof Date || obj instanceof RegExp || obj instanceof Function || obj instanceof Error || obj instanceof Map || obj instanceof Set || obj instanceof WeakMap || obj instanceof WeakSet || obj instanceof Promise || Symbol.iterator in Object(obj);
|
|
30
19
|
}
|
|
31
20
|
export {
|
|
32
21
|
sort
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamtamchik/json-deep-sort",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "A comprehensive utility for sorting JSON objects by keys.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
],
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/jest": "^29.5.12",
|
|
36
|
-
"@types/node": "^
|
|
36
|
+
"@types/node": "^22.3.0",
|
|
37
37
|
"jest": "^29.7.0",
|
|
38
|
-
"ts-jest": "^29.2.
|
|
39
|
-
"tsup": "^8.2.
|
|
38
|
+
"ts-jest": "^29.2.4",
|
|
39
|
+
"tsup": "^8.2.4",
|
|
40
40
|
"typescript": "^5.5.4"
|
|
41
41
|
},
|
|
42
42
|
"exports": {
|
package/src/index.ts
CHANGED
|
@@ -1,64 +1,41 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Enumeration of data types.
|
|
3
|
-
* @enum {string}
|
|
4
|
-
*/
|
|
5
|
-
enum DataType {
|
|
6
|
-
OBJECT,
|
|
7
|
-
ARRAY,
|
|
8
|
-
STRING,
|
|
9
|
-
OTHER,
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Function to determine the data type of the provided data.
|
|
14
|
-
* @param {any} data - The data to be checked.
|
|
15
|
-
* @returns {DataType} The DataType value corresponding to the data's type.
|
|
16
|
-
*/
|
|
17
|
-
function getType (data: any): DataType {
|
|
18
|
-
if (Array.isArray(data)) {
|
|
19
|
-
return DataType.ARRAY
|
|
20
|
-
} else if (typeof data === 'object' && data !== null) {
|
|
21
|
-
return DataType.OBJECT
|
|
22
|
-
} else if (typeof data === 'string') {
|
|
23
|
-
return DataType.STRING
|
|
24
|
-
} else {
|
|
25
|
-
return DataType.OTHER
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Function to determine whether the provided data is a recursive type.
|
|
31
|
-
* @param {any} data - The data to be checked.
|
|
32
|
-
* @returns {boolean} Whether the data is a recursive type.
|
|
33
|
-
*/
|
|
34
|
-
function isRecursiveType (data: any): boolean {
|
|
35
|
-
return [DataType.OBJECT, DataType.ARRAY].includes(getType(data))
|
|
36
|
-
}
|
|
37
|
-
|
|
38
1
|
/**
|
|
39
2
|
* Function to sort JSON data.
|
|
40
|
-
* @param {
|
|
3
|
+
* @param {unknown} data - The data to be sorted.
|
|
41
4
|
* @param {boolean} [asc=true] - Whether to sort in ascending order.
|
|
42
|
-
* @returns {
|
|
43
|
-
* @throws {Error} If the data is not an object or array.
|
|
5
|
+
* @returns {unknown} The sorted data.
|
|
44
6
|
*/
|
|
45
|
-
export function sort
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return data.map((d: any) => isRecursiveType(d) ? sort(d, asc) : d)
|
|
7
|
+
export function sort(data: unknown, asc: boolean = true): unknown {
|
|
8
|
+
if (!data || typeof data !== 'object') {
|
|
9
|
+
return data;
|
|
10
|
+
}
|
|
50
11
|
|
|
51
|
-
|
|
52
|
-
|
|
12
|
+
if (Array.isArray(data)) {
|
|
13
|
+
return data.map(item => sort(item, asc));
|
|
14
|
+
}
|
|
53
15
|
|
|
54
|
-
|
|
16
|
+
if (isNonSortableObject(data)) {
|
|
17
|
+
return data;
|
|
18
|
+
}
|
|
55
19
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
20
|
+
const sortedEntries = Object.entries(data as Record<string, unknown>)
|
|
21
|
+
.sort(([a], [b]) => asc ? a.localeCompare(b) : b.localeCompare(a));
|
|
22
|
+
|
|
23
|
+
return Object.fromEntries(
|
|
24
|
+
sortedEntries.map(([key, value]) => [key, sort(value, asc)])
|
|
25
|
+
);
|
|
26
|
+
}
|
|
60
27
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
28
|
+
function isNonSortableObject(obj: object): boolean {
|
|
29
|
+
return (
|
|
30
|
+
obj instanceof Date ||
|
|
31
|
+
obj instanceof RegExp ||
|
|
32
|
+
obj instanceof Function ||
|
|
33
|
+
obj instanceof Error ||
|
|
34
|
+
obj instanceof Map ||
|
|
35
|
+
obj instanceof Set ||
|
|
36
|
+
obj instanceof WeakMap ||
|
|
37
|
+
obj instanceof WeakSet ||
|
|
38
|
+
obj instanceof Promise ||
|
|
39
|
+
Symbol.iterator in Object(obj)
|
|
40
|
+
);
|
|
64
41
|
}
|