0
# JSON Utilities
1
2
Comprehensive type system and utilities for type-safe JSON data manipulation including deep equality comparison, deep copying, and type checking functions with support for readonly and partial variants.
3
4
## Capabilities
5
6
### JSON Type System
7
8
Complete TypeScript type definitions for JSON data with support for readonly and partial variants.
9
10
```typescript { .api }
11
// Primitive JSON Types
12
type JSONPrimitive = boolean | number | string | null;
13
14
// Core JSON Types
15
type JSONValue = JSONPrimitive | JSONObject | JSONArray;
16
interface JSONObject {
17
[key: string]: JSONValue;
18
}
19
interface JSONArray extends Array<JSONValue> {}
20
21
// Readonly JSON Types
22
type ReadonlyJSONValue = JSONPrimitive | ReadonlyJSONObject | ReadonlyJSONArray;
23
interface ReadonlyJSONObject {
24
readonly [key: string]: ReadonlyJSONValue;
25
}
26
interface ReadonlyJSONArray extends ReadonlyArray<ReadonlyJSONValue> {}
27
28
// Partial JSON Types (allows undefined values)
29
type PartialJSONValue = JSONPrimitive | PartialJSONObject | PartialJSONArray;
30
interface PartialJSONObject {
31
[key: string]: PartialJSONValue | undefined;
32
}
33
interface PartialJSONArray extends Array<PartialJSONValue> {}
34
35
// Readonly Partial JSON Types
36
type ReadonlyPartialJSONValue = JSONPrimitive | ReadonlyPartialJSONObject | ReadonlyPartialJSONArray;
37
interface ReadonlyPartialJSONObject {
38
readonly [key: string]: ReadonlyPartialJSONValue | undefined;
39
}
40
interface ReadonlyPartialJSONArray extends ReadonlyArray<ReadonlyPartialJSONValue> {}
41
```
42
43
### JSONExt Namespace
44
45
Utility functions and constants for JSON data manipulation.
46
47
```typescript { .api }
48
namespace JSONExt {
49
/**
50
* Shared frozen empty JSON object constant
51
*/
52
const emptyObject: ReadonlyJSONObject;
53
54
/**
55
* Shared frozen empty JSON array constant
56
*/
57
const emptyArray: ReadonlyJSONArray;
58
59
/**
60
* Test whether a JSON value is a primitive
61
* @param value - The JSON value to test
62
* @returns true if the value is a primitive (boolean, number, string, or null)
63
*/
64
function isPrimitive(value: ReadonlyPartialJSONValue): value is JSONPrimitive;
65
66
/**
67
* Test whether a JSON value is an array (overloaded for different JSON types)
68
* @param value - The JSON value to test
69
* @returns true if the value is an array
70
*/
71
function isArray(value: JSONValue): value is JSONArray;
72
function isArray(value: ReadonlyJSONValue): value is ReadonlyJSONArray;
73
function isArray(value: PartialJSONValue): value is PartialJSONArray;
74
function isArray(value: ReadonlyPartialJSONValue): value is ReadonlyPartialJSONArray;
75
76
/**
77
* Test whether a JSON value is an object (overloaded for different JSON types)
78
* @param value - The JSON value to test
79
* @returns true if the value is an object (not primitive or array)
80
*/
81
function isObject(value: JSONValue): value is JSONObject;
82
function isObject(value: ReadonlyJSONValue): value is ReadonlyJSONObject;
83
function isObject(value: PartialJSONValue): value is PartialJSONObject;
84
function isObject(value: ReadonlyPartialJSONValue): value is ReadonlyPartialJSONObject;
85
86
/**
87
* Compare two JSON values for deep equality
88
* @param first - The first JSON value to compare
89
* @param second - The second JSON value to compare
90
* @returns true if the values are deeply equal, false otherwise
91
*/
92
function deepEqual(
93
first: ReadonlyPartialJSONValue,
94
second: ReadonlyPartialJSONValue
95
): boolean;
96
97
/**
98
* Create a deep copy of a JSON value
99
* @param value - The JSON value to copy
100
* @returns A deep copy of the given JSON value
101
*/
102
function deepCopy<T extends ReadonlyPartialJSONValue>(value: T): T;
103
}
104
```
105
106
**Usage Examples:**
107
108
```typescript
109
import { JSONExt, JSONValue, JSONObject } from "@lumino/coreutils";
110
111
// Using constants
112
const defaultConfig = JSONExt.emptyObject;
113
const defaultItems = JSONExt.emptyArray;
114
115
// Type checking
116
const data: JSONValue = { name: "Alice", scores: [95, 87, 92] };
117
118
if (JSONExt.isPrimitive(data)) {
119
// data is boolean | number | string | null
120
console.log("Primitive value:", data);
121
} else if (JSONExt.isArray(data)) {
122
// data is JSONArray
123
console.log("Array length:", data.length);
124
} else if (JSONExt.isObject(data)) {
125
// data is JSONObject
126
console.log("Object keys:", Object.keys(data));
127
}
128
129
// Deep equality comparison
130
const obj1 = { a: 1, b: { c: 2, d: [3, 4] } };
131
const obj2 = { a: 1, b: { c: 2, d: [3, 4] } };
132
const isEqual = JSONExt.deepEqual(obj1, obj2); // true
133
134
// Deep copying
135
const original = { user: { name: "Bob", preferences: { theme: "dark" } } };
136
const copy = JSONExt.deepCopy(original);
137
copy.user.name = "Charlie"; // original.user.name remains "Bob"
138
139
// Working with partial data (allows undefined)
140
const partialUser = { name: "Alice", age: undefined, email: "alice@example.com" };
141
const userCopy = JSONExt.deepCopy(partialUser);
142
```
143
144
### Constants
145
146
Pre-defined immutable JSON objects for common use cases.
147
148
```typescript { .api }
149
/**
150
* Shared frozen empty JSON object - use instead of creating new empty objects
151
*/
152
const emptyObject: ReadonlyJSONObject;
153
154
/**
155
* Shared frozen empty JSON array - use instead of creating new empty arrays
156
*/
157
const emptyArray: ReadonlyJSONArray;
158
```
159
160
**Usage Examples:**
161
162
```typescript
163
import { JSONExt } from "@lumino/coreutils";
164
165
// Use shared constants instead of creating new objects
166
const defaultSettings = JSONExt.emptyObject;
167
const defaultItems = JSONExt.emptyArray;
168
169
// These are frozen objects, cannot be modified
170
try {
171
defaultSettings.newProperty = "value"; // TypeError in strict mode
172
} catch (error) {
173
console.log("Cannot modify frozen object");
174
}
175
```