0
# Message Serialization
1
2
High-performance binary serialization and deserialization with full type safety, validation, and conversion capabilities for protobuf messages.
3
4
## Capabilities
5
6
### Message Class
7
8
Base message class providing static methods for all serialization operations and instance methods for message manipulation.
9
10
```javascript { .api }
11
class Message<T extends object = object> {
12
/**
13
* Message type reference
14
*/
15
$type: Type;
16
17
/**
18
* Creates message instance from properties
19
* @param properties - Message properties
20
* @returns Message instance
21
*/
22
static create<T extends Message<T>>(this: Constructor<T>, properties?: { [k: string]: any }): T;
23
24
/**
25
* Encodes message to writer
26
* @param message - Message instance or plain object
27
* @param writer - Writer to encode to, creates new if omitted
28
* @returns Writer with encoded data
29
*/
30
static encode<T extends Message<T>>(this: Constructor<T>, message: T | { [k: string]: any }, writer?: Writer): Writer;
31
32
/**
33
* Encodes message with length delimiter
34
* @param message - Message instance or plain object
35
* @param writer - Writer to encode to, creates new if omitted
36
* @returns Writer with encoded data
37
*/
38
static encodeDelimited<T extends Message<T>>(this: Constructor<T>, message: T | { [k: string]: any }, writer?: Writer): Writer;
39
40
/**
41
* Decodes message from reader or buffer
42
* @param reader - Reader or buffer to decode from
43
* @param length - Message length if known
44
* @returns Decoded message instance
45
*/
46
static decode<T extends Message<T>>(this: Constructor<T>, reader: Reader | Uint8Array, length?: number): T;
47
48
/**
49
* Decodes length-delimited message
50
* @param reader - Reader or buffer to decode from
51
* @returns Decoded message instance
52
*/
53
static decodeDelimited<T extends Message<T>>(this: Constructor<T>, reader: Reader | Uint8Array): T;
54
55
/**
56
* Verifies message properties
57
* @param message - Message properties to verify
58
* @returns Error message or null if valid
59
*/
60
static verify(message: { [k: string]: any }): string | null;
61
62
/**
63
* Creates message from plain object
64
* @param object - Plain object to convert
65
* @returns Message instance
66
*/
67
static fromObject<T extends Message<T>>(this: Constructor<T>, object: { [k: string]: any }): T;
68
69
/**
70
* Converts message to plain object
71
* @param message - Message instance to convert
72
* @param options - Conversion options
73
* @returns Plain object representation
74
*/
75
static toObject<T extends Message<T>>(message: T, options?: IConversionOptions): { [k: string]: any };
76
77
/**
78
* Converts message to JSON representation
79
* @returns JSON object
80
*/
81
toJSON(): { [k: string]: any };
82
83
/**
84
* Checks if message equals another message
85
* @param message - Message to compare with
86
* @returns True if messages are equal
87
*/
88
equals(message: Message): boolean;
89
}
90
```
91
92
**Usage Examples:**
93
94
```javascript
95
const protobuf = require("protobufjs");
96
97
// Load schema and get message type
98
protobuf.load("schema.proto", function(err, root) {
99
const User = root.lookupType("User");
100
101
// Create message
102
const user = User.create({
103
id: 123,
104
name: "John Doe",
105
email: "john@example.com"
106
});
107
108
// Encode to binary
109
const buffer = User.encode(user).finish();
110
console.log("Encoded size:", buffer.length);
111
112
// Decode from binary
113
const decoded = User.decode(buffer);
114
console.log("Decoded:", decoded);
115
116
// Verify message structure
117
const errorMsg = User.verify({
118
id: "invalid", // Should be number
119
name: "Valid Name"
120
});
121
if (errorMsg) console.log("Validation error:", errorMsg);
122
});
123
```
124
125
### Type-Based Operations
126
127
Operations available on Type instances for message manipulation.
128
129
```javascript { .api }
130
class Type extends Namespace {
131
/**
132
* Creates message instance with type validation
133
* @param properties - Message properties
134
* @returns Message instance
135
*/
136
create(properties?: { [k: string]: any }): Message;
137
138
/**
139
* Encodes message with type information
140
* @param message - Message to encode
141
* @param writer - Optional writer
142
* @returns Writer with encoded data
143
*/
144
encode(message: Message | { [k: string]: any }, writer?: Writer): Writer;
145
146
/**
147
* Encodes message with length delimiter
148
* @param message - Message to encode
149
* @param writer - Optional writer
150
* @returns Writer with encoded data
151
*/
152
encodeDelimited(message: Message | { [k: string]: any }, writer?: Writer): Writer;
153
154
/**
155
* Decodes message using type schema
156
* @param reader - Reader or buffer
157
* @param length - Optional message length
158
* @returns Decoded message
159
*/
160
decode(reader: Reader | Uint8Array, length?: number): Message;
161
162
/**
163
* Decodes length-delimited message
164
* @param reader - Reader or buffer
165
* @returns Decoded message
166
*/
167
decodeDelimited(reader: Reader | Uint8Array): Message;
168
169
/**
170
* Verifies message against type schema
171
* @param message - Message to verify
172
* @returns Error message or null
173
*/
174
verify(message: { [k: string]: any }): string | null;
175
176
/**
177
* Creates message from plain object with type conversion
178
* @param object - Plain object
179
* @returns Message instance
180
*/
181
fromObject(object: { [k: string]: any }): Message;
182
183
/**
184
* Converts message to plain object with type information
185
* @param message - Message to convert
186
* @param options - Conversion options
187
* @returns Plain object
188
*/
189
toObject(message: Message, options?: IConversionOptions): { [k: string]: any };
190
}
191
```
192
193
**Usage Examples:**
194
195
```javascript
196
// Using Type methods directly
197
const MessageType = root.lookupType("package.Message");
198
199
// Create and encode
200
const message = MessageType.create({ field1: "value", field2: 42 });
201
const encoded = MessageType.encode(message).finish();
202
203
// Decode and verify
204
const decoded = MessageType.decode(encoded);
205
const valid = MessageType.verify(decoded);
206
if (valid === null) {
207
console.log("Message is valid");
208
}
209
210
// Object conversion
211
const plainObject = MessageType.toObject(message, {
212
longs: String,
213
enums: String,
214
bytes: String
215
});
216
```
217
218
### Conversion Options
219
220
Configuration options for controlling serialization behavior and data type representation.
221
222
```javascript { .api }
223
interface IConversionOptions {
224
/**
225
* Long number representation
226
* - String: Convert to string representation
227
* - Number: Convert to JavaScript number (may lose precision)
228
* - Long: Keep as Long object
229
*/
230
longs?: typeof String | typeof Number | typeof Long;
231
232
/**
233
* Enum value representation
234
* - String: Use enum names
235
* - Number: Use enum numeric values
236
*/
237
enums?: typeof String | typeof Number;
238
239
/**
240
* Byte array representation
241
* - Array: Convert to number array
242
* - String: Convert to base64 string
243
* - Uint8Array: Keep as Uint8Array
244
*/
245
bytes?: typeof Array | typeof String | typeof Uint8Array;
246
247
/**
248
* Whether to include default values
249
*/
250
defaults?: boolean;
251
252
/**
253
* Whether to include empty arrays
254
*/
255
arrays?: boolean;
256
257
/**
258
* Whether to include empty objects
259
*/
260
objects?: boolean;
261
262
/**
263
* Whether to include oneof properties that aren't set
264
*/
265
oneofs?: boolean;
266
}
267
```
268
269
**Usage Examples:**
270
271
```javascript
272
const message = MessageType.create({
273
id: Long.fromNumber(123456789012345),
274
status: StatusEnum.values.ACTIVE,
275
data: new Uint8Array([1, 2, 3, 4])
276
});
277
278
// Convert with different options
279
const jsonFriendly = MessageType.toObject(message, {
280
longs: String, // "123456789012345"
281
enums: String, // "ACTIVE"
282
bytes: String, // base64 encoded
283
defaults: true // include default values
284
});
285
286
const numeric = MessageType.toObject(message, {
287
longs: Number, // 123456789012345 (may lose precision)
288
enums: Number, // 1
289
bytes: Array // [1, 2, 3, 4]
290
});
291
```
292
293
### Validation
294
295
Message validation capabilities for ensuring data integrity and type safety.
296
297
```javascript { .api }
298
/**
299
* Validates message properties against schema
300
* @param message - Message properties to validate
301
* @returns Error message string or null if valid
302
*/
303
function verify(message: { [k: string]: any }): string | null;
304
305
// Validation error types
306
interface ValidationErrors {
307
missingField: string; // "missing required field"
308
invalidType: string; // "invalid type for field"
309
outOfRange: string; // "value out of range"
310
invalidEnum: string; // "invalid enum value"
311
invalidOneOf: string; // "multiple oneof fields set"
312
}
313
```
314
315
**Usage Examples:**
316
317
```javascript
318
// Validate before encoding
319
const messageData = {
320
id: "not-a-number", // Invalid type
321
name: "", // Empty string
322
age: -5 // Invalid value
323
};
324
325
const error = MessageType.verify(messageData);
326
if (error) {
327
console.log("Validation failed:", error);
328
// Handle validation error
329
} else {
330
// Safe to create and encode
331
const message = MessageType.create(messageData);
332
const encoded = MessageType.encode(message).finish();
333
}
334
335
// Validate after decoding
336
const decoded = MessageType.decode(someBuffer);
337
const valid = MessageType.verify(decoded);
338
if (valid !== null) {
339
console.warn("Decoded message validation warning:", valid);
340
}
341
```
342
343
### Binary Format Operations
344
345
Low-level binary format operations for custom serialization needs.
346
347
```javascript { .api }
348
/**
349
* Finishes writer operations and returns encoded buffer
350
* @returns Encoded binary data
351
*/
352
Writer.prototype.finish(): Uint8Array;
353
354
/**
355
* Gets current writer length
356
* @returns Number of bytes written
357
*/
358
Writer.prototype.len: number;
359
360
/**
361
* Creates reader from binary data
362
* @param buffer - Binary data to read
363
* @returns Reader instance
364
*/
365
Reader.create(buffer: Uint8Array): Reader;
366
367
/**
368
* Current reader position
369
*/
370
Reader.prototype.pos: number;
371
372
/**
373
* Total buffer length
374
*/
375
Reader.prototype.len: number;
376
```
377
378
**Usage Examples:**
379
380
```javascript
381
// Custom encoding with length tracking
382
const writer = protobuf.Writer.create();
383
const message1 = Type1.encode(data1, writer);
384
const pos1 = writer.len;
385
386
const message2 = Type2.encode(data2, writer);
387
const pos2 = writer.len;
388
389
const buffer = writer.finish();
390
console.log(`Total size: ${buffer.length}, Message1: ${pos1}, Message2: ${pos2 - pos1}`);
391
392
// Custom decoding with position tracking
393
const reader = protobuf.Reader.create(buffer);
394
const decoded1 = Type1.decode(reader, pos1);
395
const decoded2 = Type2.decode(reader);
396
console.log(`Reader position: ${reader.pos}/${reader.len}`);
397
```
398
399
### Error Handling
400
401
Common error conditions and handling patterns in serialization operations.
402
403
```javascript { .api }
404
interface SerializationError extends Error {
405
name: string; // Error type
406
message: string; // Error description
407
path?: string; // Field path that caused error
408
instance?: any; // Problematic value
409
}
410
411
// Common error types
412
interface ErrorTypes {
413
TypeError: "invalid type";
414
RangeError: "value out of range";
415
Error: "general serialization error";
416
}
417
```
418
419
**Usage Examples:**
420
421
```javascript
422
try {
423
// Encoding errors
424
const message = MessageType.create({
425
requiredField: null, // Missing required field
426
enumField: 999 // Invalid enum value
427
});
428
const encoded = MessageType.encode(message).finish();
429
} catch (err) {
430
console.error("Encoding error:", err.message);
431
if (err.path) console.error("Field path:", err.path);
432
}
433
434
try {
435
// Decoding errors
436
const corrupted = new Uint8Array([0xFF, 0xFF, 0xFF]);
437
const decoded = MessageType.decode(corrupted);
438
} catch (err) {
439
console.error("Decoding error:", err.message);
440
}
441
```
442
443
## Types
444
445
```javascript { .api }
446
interface Constructor<T> extends Function {
447
new (...args: any[]): T;
448
}
449
450
interface IConversionOptions {
451
longs?: typeof String | typeof Number | typeof Long;
452
enums?: typeof String | typeof Number;
453
bytes?: typeof Array | typeof String | typeof Uint8Array;
454
defaults?: boolean;
455
arrays?: boolean;
456
objects?: boolean;
457
oneofs?: boolean;
458
}
459
460
interface Long {
461
low: number;
462
high: number;
463
unsigned: boolean;
464
toNumber(): number;
465
toString(): string;
466
equals(other: Long): boolean;
467
static fromNumber(value: number): Long;
468
static fromString(value: string): Long;
469
}
470
```