ts-serializable 4.2.2 → 4.3.2
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 +676 -40
- package/dist/classes/Serializable.d.ts +147 -66
- package/dist/classes/Serializable.js +153 -191
- package/dist/functions/ClassToFormData.d.ts +34 -0
- package/dist/{utils → functions}/ClassToFormData.js +31 -6
- package/dist/functions/DeserializeProperty.d.ts +38 -0
- package/dist/functions/DeserializeProperty.js +142 -0
- package/dist/functions/FromJSON.d.ts +56 -0
- package/dist/functions/FromJSON.js +97 -0
- package/dist/functions/GetPropertyName.d.ts +38 -0
- package/dist/functions/GetPropertyName.js +56 -0
- package/dist/functions/OnWrongType.d.ts +23 -0
- package/dist/functions/OnWrongType.js +27 -0
- package/dist/functions/ToJSON.d.ts +36 -0
- package/dist/functions/ToJSON.js +57 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.js +7 -3
- package/package.json +7 -7
- package/dist/utils/ClassToFormData.d.ts +0 -9
- package/dist/utils/GetProperyName.d.ts +0 -10
- package/dist/utils/GetProperyName.js +0 -28
|
@@ -1,22 +1,35 @@
|
|
|
1
|
-
/* eslint-disable max-lines */
|
|
2
|
-
/* eslint-disable no-prototype-builtins */
|
|
3
|
-
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
4
|
-
/* eslint-disable complexity */
|
|
5
|
-
/* eslint-disable max-lines-per-function */
|
|
6
|
-
/* eslint-disable max-statements */
|
|
7
1
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
2
|
+
import { deserializeProperty } from "../functions/DeserializeProperty.js";
|
|
8
3
|
import { SerializationSettings } from "../models/SerializationSettings.js";
|
|
9
|
-
import { classToFormData } from "../
|
|
10
|
-
import { getPropertyName } from "../
|
|
4
|
+
import { classToFormData } from "../functions/ClassToFormData.js";
|
|
5
|
+
import { getPropertyName } from "../functions/GetPropertyName.js";
|
|
6
|
+
import { fromJSON } from "../functions/FromJSON.js";
|
|
7
|
+
import { toJSON } from "../functions/ToJSON.js";
|
|
11
8
|
/**
|
|
12
|
-
*
|
|
9
|
+
* Base class that provides serialization and deserialization functionality for converting
|
|
10
|
+
* objects to and from JSON format. This class uses decorators to define how properties
|
|
11
|
+
* should be serialized and deserialized.
|
|
13
12
|
*
|
|
14
13
|
* @export
|
|
15
14
|
* @class Serializable
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* class User extends Serializable {
|
|
18
|
+
* @JsonProperty()
|
|
19
|
+
* name: string;
|
|
20
|
+
*
|
|
21
|
+
* @JsonProperty()
|
|
22
|
+
* age: number;
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* const user = User.fromJSON({ name: "John", age: 30 });
|
|
26
|
+
* const json = user.toJSON();
|
|
27
|
+
* ```
|
|
16
28
|
*/
|
|
17
29
|
export class Serializable {
|
|
18
30
|
/**
|
|
19
|
-
* Global settings for serialization and deserialization.
|
|
31
|
+
* Global default settings for all serialization and deserialization operations.
|
|
32
|
+
* These settings can be overridden per operation by passing custom settings.
|
|
20
33
|
*
|
|
21
34
|
* @static
|
|
22
35
|
* @type {SerializationSettings}
|
|
@@ -24,245 +37,194 @@ export class Serializable {
|
|
|
24
37
|
*/
|
|
25
38
|
static defaultSettings = new SerializationSettings();
|
|
26
39
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* Example:
|
|
30
|
-
* const obj: MyObject = MyObject.fromJSON({...data});
|
|
40
|
+
* Creates a new instance of the class and deserializes JSON data into it.
|
|
41
|
+
* This is a convenient static method that combines instantiation and deserialization.
|
|
31
42
|
*
|
|
32
43
|
* @static
|
|
33
|
-
* @
|
|
34
|
-
* @
|
|
44
|
+
* @template T - The type of the Serializable class
|
|
45
|
+
* @param {object} json - The JSON object to deserialize
|
|
46
|
+
* @param {Partial<SerializationSettings>} [settings] - Optional settings to override default serialization behavior
|
|
47
|
+
* @returns {T} A new instance of the class with properties populated from the JSON
|
|
35
48
|
* @memberof Serializable
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const user = User.fromJSON({ name: "John", age: 30 });
|
|
52
|
+
* ```
|
|
36
53
|
*/
|
|
37
54
|
static fromJSON(json, settings) {
|
|
38
55
|
return new this().fromJSON(json, settings);
|
|
39
56
|
}
|
|
40
57
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* Example:
|
|
44
|
-
* const obj: MyObject = MyObject.fromString("{...data}");
|
|
58
|
+
* Creates a new instance of the class and deserializes JSON string data into it.
|
|
59
|
+
* Automatically parses the JSON string before deserialization.
|
|
45
60
|
*
|
|
46
61
|
* @static
|
|
47
|
-
* @
|
|
48
|
-
* @
|
|
62
|
+
* @template T - The type of the Serializable class
|
|
63
|
+
* @param {string} str - The JSON string to parse and deserialize
|
|
64
|
+
* @param {Partial<SerializationSettings>} [settings] - Optional settings to override default serialization behavior
|
|
65
|
+
* @returns {T} A new instance of the class with properties populated from the parsed JSON
|
|
49
66
|
* @memberof Serializable
|
|
67
|
+
* @throws {SyntaxError} If the string is not valid JSON
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* const user = User.fromString('{"name":"John","age":30}');
|
|
71
|
+
* ```
|
|
50
72
|
*/
|
|
51
73
|
static fromString(str, settings) {
|
|
52
74
|
return new this().fromJSON(JSON.parse(str), settings);
|
|
53
75
|
}
|
|
54
76
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* Example:
|
|
58
|
-
* const obj: MyObject = new MyObject().fromString("{...data}");
|
|
77
|
+
* Populates the current instance's properties with data from a JSON object.
|
|
78
|
+
* Uses metadata from decorators to determine how to deserialize each property.
|
|
59
79
|
*
|
|
60
|
-
* @param {
|
|
61
|
-
* @
|
|
80
|
+
* @param {object} json - The JSON object containing data to populate the instance
|
|
81
|
+
* @param {Partial<SerializationSettings>} [settings] - Optional settings to override default serialization behavior
|
|
82
|
+
* @returns {this} The current instance for method chaining
|
|
62
83
|
* @memberof Serializable
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* const user = new User();
|
|
87
|
+
* user.fromJSON({ name: "John", age: 30 });
|
|
88
|
+
* ```
|
|
63
89
|
*/
|
|
64
|
-
|
|
65
|
-
return
|
|
90
|
+
fromJSON(json, settings) {
|
|
91
|
+
return fromJSON(this, json, settings);
|
|
66
92
|
}
|
|
67
93
|
/**
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* Example:
|
|
71
|
-
* const obj: MyObject = new MyObject().fromJSON({...data});
|
|
94
|
+
* Populates the current instance's properties with data from a JSON string.
|
|
95
|
+
* Automatically parses the JSON string before populating properties.
|
|
72
96
|
*
|
|
73
|
-
* @param {
|
|
74
|
-
* @
|
|
97
|
+
* @param {string} str - The JSON string to parse and use for populating the instance
|
|
98
|
+
* @param {Partial<SerializationSettings>} [settings] - Optional settings to override default serialization behavior
|
|
99
|
+
* @returns {this} The current instance for method chaining
|
|
75
100
|
* @memberof Serializable
|
|
101
|
+
* @throws {SyntaxError} If the string is not valid JSON
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* const user = new User();
|
|
105
|
+
* user.fromString('{"name":"John","age":30}');
|
|
106
|
+
* ```
|
|
76
107
|
*/
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (unknownJson === null ||
|
|
80
|
-
Array.isArray(unknownJson) ||
|
|
81
|
-
typeof unknownJson !== "object") {
|
|
82
|
-
this.onWrongType(String(unknownJson), "is not an object", unknownJson);
|
|
83
|
-
return this;
|
|
84
|
-
}
|
|
85
|
-
// eslint-disable-next-line guard-for-in
|
|
86
|
-
for (const thisProp in this) {
|
|
87
|
-
// Naming strategy and jsonName decorator
|
|
88
|
-
let jsonProp = this.getJsonPropertyName(thisProp, settings);
|
|
89
|
-
// For deep copy
|
|
90
|
-
if (!unknownJson?.hasOwnProperty(jsonProp) && unknownJson?.hasOwnProperty(thisProp)) {
|
|
91
|
-
jsonProp = thisProp;
|
|
92
|
-
}
|
|
93
|
-
if (unknownJson?.hasOwnProperty(jsonProp) &&
|
|
94
|
-
this.hasOwnProperty(thisProp) &&
|
|
95
|
-
Reflect.hasMetadata("ts-serializable:jsonTypes", this.constructor.prototype, thisProp)) {
|
|
96
|
-
const acceptedTypes = Reflect.getMetadata("ts-serializable:jsonTypes", this.constructor.prototype, thisProp);
|
|
97
|
-
const jsonValue = Reflect.get(unknownJson, jsonProp);
|
|
98
|
-
const extractedValue = this.deserializeProperty(thisProp, acceptedTypes, jsonValue, settings);
|
|
99
|
-
Reflect.set(this, thisProp, extractedValue);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return this;
|
|
108
|
+
fromString(str, settings) {
|
|
109
|
+
return this.fromJSON(JSON.parse(str), settings);
|
|
103
110
|
}
|
|
104
111
|
/**
|
|
105
|
-
*
|
|
112
|
+
* Serializes the current instance to a plain JavaScript object.
|
|
113
|
+
* Respects @JsonIgnore decorators to exclude specific properties from serialization.
|
|
114
|
+
* Applies naming strategies and @JsonName decorators for property name transformation.
|
|
106
115
|
*
|
|
107
|
-
* @returns {object
|
|
116
|
+
* @returns {Record<string, unknown>} A plain object representation of the instance
|
|
108
117
|
* @memberof Serializable
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* const user = new User();
|
|
121
|
+
* user.name = "John";
|
|
122
|
+
* user.age = 30;
|
|
123
|
+
* const json = user.toJSON(); // { name: "John", age: 30 }
|
|
124
|
+
* ```
|
|
109
125
|
*/
|
|
110
126
|
toJSON() {
|
|
111
|
-
|
|
112
|
-
const keys = Reflect.ownKeys(this);
|
|
113
|
-
for (const key of keys) {
|
|
114
|
-
if (typeof key === "symbol") {
|
|
115
|
-
// eslint-disable-next-line no-continue
|
|
116
|
-
continue;
|
|
117
|
-
}
|
|
118
|
-
if (this.hasOwnProperty(key)) {
|
|
119
|
-
if (Reflect.getMetadata("ts-serializable:jsonIgnore", this.constructor.prototype, key) !== true) {
|
|
120
|
-
const toProp = this.getJsonPropertyName(key);
|
|
121
|
-
Reflect.set(toJson, toProp, Reflect.get(this, key));
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
return toJson;
|
|
127
|
+
return toJSON(this);
|
|
126
128
|
}
|
|
127
129
|
/**
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
* @
|
|
136
|
-
* @param {FormData} formData Can update an existing FormData
|
|
137
|
-
* @returns {FormData}
|
|
130
|
+
* Serializes the current instance to FormData format, suitable for multipart/form-data requests.
|
|
131
|
+
* This is particularly useful for AJAX form submissions that include file uploads.
|
|
132
|
+
* Unlike JSON serialization with base64-encoded files, FormData provides better performance
|
|
133
|
+
* and avoids UI freezing when handling large files.
|
|
134
|
+
*
|
|
135
|
+
* @param {string} [formPrefix] - Optional prefix to prepend to all form field names
|
|
136
|
+
* @param {FormData} [formData] - Optional existing FormData instance to append to
|
|
137
|
+
* @returns {FormData} A FormData instance containing the serialized data
|
|
138
138
|
* @memberof Serializable
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* const user = new User();
|
|
142
|
+
* user.name = "John";
|
|
143
|
+
* user.avatar = fileInput.files[0];
|
|
144
|
+
* const formData = user.toFormData();
|
|
145
|
+
* // Use with fetch: fetch('/api/users', { method: 'POST', body: formData });
|
|
146
|
+
* ```
|
|
139
147
|
*/
|
|
140
148
|
toFormData(formPrefix, formData) {
|
|
141
149
|
return classToFormData(this, formPrefix, formData);
|
|
142
150
|
}
|
|
143
151
|
/**
|
|
144
|
-
*
|
|
152
|
+
* Serializes the current instance to a JSON string.
|
|
153
|
+
* This is a convenience method that combines toJSON() with JSON.stringify().
|
|
145
154
|
*
|
|
146
|
-
* @returns {string}
|
|
155
|
+
* @returns {string} A JSON string representation of the instance
|
|
147
156
|
* @memberof Serializable
|
|
157
|
+
* @example
|
|
158
|
+
* ```typescript
|
|
159
|
+
* const user = new User();
|
|
160
|
+
* user.name = "John";
|
|
161
|
+
* user.age = 30;
|
|
162
|
+
* const jsonString = user.toString(); // '{"name":"John","age":30}'
|
|
163
|
+
* ```
|
|
148
164
|
*/
|
|
149
165
|
toString() {
|
|
150
166
|
return JSON.stringify(this.toJSON());
|
|
151
167
|
}
|
|
152
168
|
/**
|
|
153
|
-
*
|
|
154
|
-
* By default,
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
* @
|
|
159
|
-
* @param {
|
|
169
|
+
* Handles type mismatch errors during deserialization.
|
|
170
|
+
* By default, logs an error to the console. Can be overridden in subclasses to implement
|
|
171
|
+
* custom error handling such as throwing exceptions, logging to external services, or
|
|
172
|
+
* collecting validation errors.
|
|
173
|
+
*
|
|
174
|
+
* @public
|
|
175
|
+
* @param {string} prop - The name of the property that has a type mismatch
|
|
176
|
+
* @param {string} message - A description of the type error
|
|
177
|
+
* @param {unknown} jsonValue - The actual value that caused the type mismatch
|
|
160
178
|
* @memberof Serializable
|
|
179
|
+
* @example
|
|
180
|
+
* ```typescript
|
|
181
|
+
* class User extends Serializable {
|
|
182
|
+
* onWrongType(prop: string, message: string, jsonValue: unknown): void {
|
|
183
|
+
* throw new Error(`Invalid ${prop}: ${message}`);
|
|
184
|
+
* }
|
|
185
|
+
* }
|
|
186
|
+
* ```
|
|
161
187
|
*/
|
|
162
188
|
onWrongType(prop, message, jsonValue) {
|
|
163
189
|
// eslint-disable-next-line no-console
|
|
164
190
|
console.error(`${this.constructor.name}.fromJSON: json.${prop} ${message}:`, jsonValue);
|
|
165
191
|
}
|
|
166
192
|
/**
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
* @
|
|
172
|
-
* @param {
|
|
173
|
-
* @param {
|
|
174
|
-
* @
|
|
193
|
+
* Deserializes a single property value based on its accepted types.
|
|
194
|
+
* This method is used internally during deserialization to convert JSON values
|
|
195
|
+
* to the appropriate TypeScript types defined by decorators.
|
|
196
|
+
*
|
|
197
|
+
* @public
|
|
198
|
+
* @param {string} prop - The name of the property being deserialized
|
|
199
|
+
* @param {AcceptedTypes[]} acceptedTypes - Array of allowed types for this property
|
|
200
|
+
* @param {unknown} jsonValue - The JSON value to deserialize
|
|
201
|
+
* @param {Partial<SerializationSettings>} [settings] - Optional settings to override default behavior
|
|
202
|
+
* @returns {unknown} The deserialized value matching one of the accepted types
|
|
175
203
|
* @memberof Serializable
|
|
176
204
|
*/
|
|
177
205
|
// eslint-disable-next-line max-params
|
|
178
206
|
deserializeProperty(prop, acceptedTypes, jsonValue, settings) {
|
|
179
|
-
|
|
180
|
-
if ( // Null
|
|
181
|
-
acceptedType === null &&
|
|
182
|
-
jsonValue === null) {
|
|
183
|
-
return null;
|
|
184
|
-
}
|
|
185
|
-
else if ( // Void, for deep copy classes only, JSON doesn't have a void type
|
|
186
|
-
acceptedType === void 0 &&
|
|
187
|
-
jsonValue === void 0) {
|
|
188
|
-
return void 0;
|
|
189
|
-
}
|
|
190
|
-
else if ( // Boolean, Boolean
|
|
191
|
-
acceptedType === Boolean &&
|
|
192
|
-
(typeof jsonValue === "boolean" || jsonValue instanceof Boolean)) {
|
|
193
|
-
return Boolean(jsonValue);
|
|
194
|
-
}
|
|
195
|
-
else if ( // Number, Number
|
|
196
|
-
acceptedType === Number &&
|
|
197
|
-
(typeof jsonValue === "number" || jsonValue instanceof Number)) {
|
|
198
|
-
return Number(jsonValue);
|
|
199
|
-
}
|
|
200
|
-
else if ( // String, String
|
|
201
|
-
acceptedType === String &&
|
|
202
|
-
(typeof jsonValue === "string" || jsonValue instanceof String)) {
|
|
203
|
-
return String(jsonValue);
|
|
204
|
-
}
|
|
205
|
-
else if ( // Object, Object
|
|
206
|
-
acceptedType === Object &&
|
|
207
|
-
(typeof jsonValue === "object")) {
|
|
208
|
-
return Object(jsonValue);
|
|
209
|
-
}
|
|
210
|
-
else if ( // Date
|
|
211
|
-
acceptedType === Date &&
|
|
212
|
-
(typeof jsonValue === "string" || jsonValue instanceof String || jsonValue instanceof Date)) {
|
|
213
|
-
// 0 year, 0 month, 0 days, 0 hours, 0 minutes, 0 seconds
|
|
214
|
-
let unicodeTime = new Date("0000-01-01T00:00:00.000").getTime();
|
|
215
|
-
if (typeof jsonValue === "string") {
|
|
216
|
-
unicodeTime = Date.parse(jsonValue);
|
|
217
|
-
}
|
|
218
|
-
else if (jsonValue instanceof String) {
|
|
219
|
-
unicodeTime = Date.parse(String(jsonValue));
|
|
220
|
-
}
|
|
221
|
-
else if (jsonValue instanceof Date) {
|
|
222
|
-
unicodeTime = jsonValue.getTime();
|
|
223
|
-
}
|
|
224
|
-
if (isNaN(unicodeTime)) { // Preserve invalid time
|
|
225
|
-
this.onWrongType(prop, "is an invalid date", jsonValue);
|
|
226
|
-
}
|
|
227
|
-
return new Date(unicodeTime);
|
|
228
|
-
}
|
|
229
|
-
else if ( // Array
|
|
230
|
-
Array.isArray(acceptedType) &&
|
|
231
|
-
Array.isArray(jsonValue)) {
|
|
232
|
-
if (acceptedType[0] === void 0) {
|
|
233
|
-
this.onWrongType(prop, "invalid type", jsonValue);
|
|
234
|
-
}
|
|
235
|
-
return jsonValue.map((arrayValue) => this.deserializeProperty(prop, acceptedType, arrayValue, settings));
|
|
236
|
-
}
|
|
237
|
-
else if ( // Serializable
|
|
238
|
-
acceptedType !== null &&
|
|
239
|
-
acceptedType !== void 0 &&
|
|
240
|
-
!Array.isArray(acceptedType) &&
|
|
241
|
-
(acceptedType.prototype instanceof Serializable ||
|
|
242
|
-
Boolean(Reflect.getMetadata("ts-serializable:jsonObjectExtended", acceptedType))) &&
|
|
243
|
-
jsonValue !== null &&
|
|
244
|
-
jsonValue !== void 0 &&
|
|
245
|
-
typeof jsonValue === "object" && !Array.isArray(jsonValue)) {
|
|
246
|
-
const TypeConstructor = acceptedType;
|
|
247
|
-
return new TypeConstructor().fromJSON(jsonValue, settings);
|
|
248
|
-
}
|
|
249
|
-
else if ( // Instance any other class, not Serializable, for parsing from other class instances
|
|
250
|
-
acceptedType instanceof Function &&
|
|
251
|
-
jsonValue instanceof acceptedType) {
|
|
252
|
-
return jsonValue;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
// Process incorrect type and return default value
|
|
256
|
-
this.onWrongType(prop, "is invalid", jsonValue);
|
|
257
|
-
return Reflect.get(this, prop);
|
|
207
|
+
return deserializeProperty(this, prop, acceptedTypes, jsonValue, settings);
|
|
258
208
|
}
|
|
259
209
|
/**
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
* @
|
|
265
|
-
* @
|
|
210
|
+
* Determines the JSON property name for a given class property.
|
|
211
|
+
* Takes into account @JsonName decorators and naming strategies (camelCase, snake_case, etc.)
|
|
212
|
+
* defined in the serialization settings.
|
|
213
|
+
*
|
|
214
|
+
* @public
|
|
215
|
+
* @param {string} property - The source property name as defined in the class
|
|
216
|
+
* @param {Partial<SerializationSettings>} [settings] - Optional settings to override default naming behavior
|
|
217
|
+
* @returns {string} The transformed property name to use in JSON
|
|
218
|
+
* @memberof Serializable
|
|
219
|
+
* @example
|
|
220
|
+
* ```typescript
|
|
221
|
+
* // With @JsonName decorator
|
|
222
|
+
* class User extends Serializable {
|
|
223
|
+
* @JsonName("user_name")
|
|
224
|
+
* userName: string;
|
|
225
|
+
* }
|
|
226
|
+
* // user.getJsonPropertyName("userName") returns "user_name"
|
|
227
|
+
* ```
|
|
266
228
|
*/
|
|
267
229
|
getJsonPropertyName(property, settings) {
|
|
268
230
|
return getPropertyName(this, property, settings);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a class instance to FormData format for multipart/form-data HTTP requests.
|
|
3
|
+
* This function recursively processes nested objects, arrays, and handles special types like File and Date.
|
|
4
|
+
* Properties marked with @JsonIgnore decorator are excluded from the conversion.
|
|
5
|
+
*
|
|
6
|
+
* @param {object} obj - The class instance or object to convert to FormData
|
|
7
|
+
* @param {string} [formPrefix] - Optional prefix for form property names (used for nested objects, e.g., "user.address")
|
|
8
|
+
* @param {FormData} [formData] - Optional existing FormData instance to append to. If not provided, creates a new one
|
|
9
|
+
* @returns {FormData} The FormData object containing all serialized properties
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const user = {
|
|
14
|
+
* name: "John",
|
|
15
|
+
* age: 30,
|
|
16
|
+
* avatar: fileInput.files[0],
|
|
17
|
+
* address: { city: "New York" }
|
|
18
|
+
* };
|
|
19
|
+
* const formData = classToFormData(user);
|
|
20
|
+
* // Results in FormData with entries:
|
|
21
|
+
* // name: "John"
|
|
22
|
+
* // age: "30"
|
|
23
|
+
* // avatar: [File object]
|
|
24
|
+
* // address.city: "New York"
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @remarks
|
|
28
|
+
* - File objects are appended directly to FormData
|
|
29
|
+
* - Date objects are converted to ISO strings
|
|
30
|
+
* - Null values are skipped
|
|
31
|
+
* - Arrays are processed recursively with indices for nested objects
|
|
32
|
+
* - Nested objects use dot notation for property names
|
|
33
|
+
*/
|
|
34
|
+
export declare const classToFormData: (obj: object, formPrefix?: string, formData?: FormData) => FormData;
|
|
@@ -1,13 +1,38 @@
|
|
|
1
1
|
/* eslint-disable max-statements */
|
|
2
2
|
/* eslint-disable max-lines-per-function */
|
|
3
|
-
import { getPropertyName } from "./
|
|
3
|
+
import { getPropertyName } from "./GetPropertyName.js";
|
|
4
4
|
/**
|
|
5
|
-
* Converts a class instance to FormData for
|
|
5
|
+
* Converts a class instance to FormData format for multipart/form-data HTTP requests.
|
|
6
|
+
* This function recursively processes nested objects, arrays, and handles special types like File and Date.
|
|
7
|
+
* Properties marked with @JsonIgnore decorator are excluded from the conversion.
|
|
6
8
|
*
|
|
7
|
-
* @param {object} obj - The class instance to convert
|
|
8
|
-
* @param {string} [formPrefix] - Optional prefix for form property names.
|
|
9
|
-
* @param {FormData} [formData] - Optional existing FormData to
|
|
10
|
-
* @returns {FormData}
|
|
9
|
+
* @param {object} obj - The class instance or object to convert to FormData
|
|
10
|
+
* @param {string} [formPrefix] - Optional prefix for form property names (used for nested objects, e.g., "user.address")
|
|
11
|
+
* @param {FormData} [formData] - Optional existing FormData instance to append to. If not provided, creates a new one
|
|
12
|
+
* @returns {FormData} The FormData object containing all serialized properties
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const user = {
|
|
17
|
+
* name: "John",
|
|
18
|
+
* age: 30,
|
|
19
|
+
* avatar: fileInput.files[0],
|
|
20
|
+
* address: { city: "New York" }
|
|
21
|
+
* };
|
|
22
|
+
* const formData = classToFormData(user);
|
|
23
|
+
* // Results in FormData with entries:
|
|
24
|
+
* // name: "John"
|
|
25
|
+
* // age: "30"
|
|
26
|
+
* // avatar: [File object]
|
|
27
|
+
* // address.city: "New York"
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* - File objects are appended directly to FormData
|
|
32
|
+
* - Date objects are converted to ISO strings
|
|
33
|
+
* - Null values are skipped
|
|
34
|
+
* - Arrays are processed recursively with indices for nested objects
|
|
35
|
+
* - Nested objects use dot notation for property names
|
|
11
36
|
*/
|
|
12
37
|
export const classToFormData = (obj, formPrefix, formData) => {
|
|
13
38
|
const newFormData = formData ?? new FormData();
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { AcceptedTypes } from "../models/AcceptedType.js";
|
|
2
|
+
import { SerializationSettings } from "../models/SerializationSettings.js";
|
|
3
|
+
/**
|
|
4
|
+
* Deserializes a single property value from JSON data based on accepted type definitions.
|
|
5
|
+
* This function iterates through accepted types and attempts to match and convert the JSON value
|
|
6
|
+
* to the appropriate TypeScript type. Supports primitives, arrays, dates, and complex object types.
|
|
7
|
+
*
|
|
8
|
+
* @param {object} obj - The object instance to which the property belongs
|
|
9
|
+
* @param {string} prop - The name of the property being deserialized
|
|
10
|
+
* @param {AcceptedTypes[]} acceptedTypes - Array of type constructors or type definitions that the property can accept
|
|
11
|
+
* @param {unknown} jsonValue - The raw JSON value to deserialize and convert
|
|
12
|
+
* @param {Partial<SerializationSettings>} [settings] - Optional settings to customize deserialization behavior
|
|
13
|
+
* @returns {unknown} The deserialized and typed value, or the original property value if no type match is found
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* Supported type conversions:
|
|
17
|
+
* - `null` - Preserves null values
|
|
18
|
+
* - `undefined` (void 0) - For deep copy operations
|
|
19
|
+
* - `Boolean` - Converts boolean values and Boolean objects
|
|
20
|
+
* - `Number` - Converts numeric values and Number objects
|
|
21
|
+
* - `String` - Converts string values and String objects
|
|
22
|
+
* - `Object` - Converts plain objects
|
|
23
|
+
* - `Date` - Parses ISO strings, Date objects, and validates date values
|
|
24
|
+
* - `Array` - Recursively deserializes array elements
|
|
25
|
+
* - `Serializable` subclasses - Creates instances and calls fromJSON
|
|
26
|
+
* - Custom classes - Creates instances and applies fromJSON for non-Serializable classes
|
|
27
|
+
* - Instance checks - Validates existing instances of specific classes
|
|
28
|
+
*
|
|
29
|
+
* If no type matches, calls `onWrongType` error handler and returns the original property value.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const acceptedTypes = [String, Number];
|
|
34
|
+
* const result = deserializeProperty(obj, "age", acceptedTypes, "30");
|
|
35
|
+
* // Returns the string "30" since String is checked first
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare const deserializeProperty: (obj: object, prop: string, acceptedTypes: AcceptedTypes[], jsonValue: unknown, settings?: Partial<SerializationSettings>) => unknown;
|