Skip to content

Commit b04a351

Browse files
committed
Call toJSON() on non-ext objects when it exists
1 parent 9770004 commit b04a351

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

Diff for: src/Encoder.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import type { ExtData } from "./ExtData";
77
export const DEFAULT_MAX_DEPTH = 100;
88
export const DEFAULT_INITIAL_BUFFER_SIZE = 2048;
99

10+
const hastoJSON = (value: unknown): value is { toJSON: unknown } => {
11+
return typeof value === 'object' && value !== null && 'toJSON' in value;
12+
};
13+
1014
export class Encoder<ContextType = undefined> {
1115
private pos = 0;
1216
private view = new DataView(new ArrayBuffer(this.initialBufferSize));
@@ -194,7 +198,11 @@ export class Encoder<ContextType = undefined> {
194198
} else if (ArrayBuffer.isView(object)) {
195199
this.encodeBinary(object);
196200
} else if (typeof object === "object") {
197-
this.encodeMap(object as Record<string, unknown>, depth);
201+
if (hastoJSON(object) && typeof object.toJSON === "function") {
202+
this.doEncode(object.toJSON(), depth);
203+
} else {
204+
this.encodeMap(object as Record<string, unknown>, depth);
205+
}
198206
} else {
199207
// symbol, function and other special object come here unless extensionCodec handles them.
200208
throw new Error(`Unrecognized object: ${Object.prototype.toString.apply(object)}`);

Diff for: test/decodeAsync.test.ts

+39
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,43 @@ describe("decodeAsync", () => {
120120
const object = await decodeAsync(createStream());
121121
assert.deepStrictEqual(object, { "foo": "bar" });
122122
});
123+
124+
it("decodes objects with toJSON methods", async () => {
125+
const object = {
126+
string: "Hello, world!",
127+
nested: {
128+
int: -45,
129+
json: {
130+
toJSON() {
131+
return {
132+
float: Math.PI,
133+
int64: Number.MIN_SAFE_INTEGER,
134+
timestamp: new Date( 0 ),
135+
custom: {
136+
toJSON: () => "custom"
137+
}
138+
}
139+
}
140+
}
141+
}
142+
};
143+
144+
const createStream = async function* () {
145+
for (const byte of encode(object)) {
146+
yield [byte];
147+
}
148+
};
149+
assert.deepStrictEqual(await decodeAsync(createStream()), {
150+
string: "Hello, world!",
151+
nested: {
152+
int: -45,
153+
json: {
154+
float: Math.PI,
155+
int64: Number.MIN_SAFE_INTEGER,
156+
timestamp: new Date( 0 ),
157+
custom: "custom"
158+
}
159+
}
160+
});
161+
});
123162
});

0 commit comments

Comments
 (0)