diff --git a/packages/pglite/src/types.ts b/packages/pglite/src/types.ts index dec8a9388..786eac52f 100644 --- a/packages/pglite/src/types.ts +++ b/packages/pglite/src/types.ts @@ -112,7 +112,9 @@ export const types = { if (typeof x === 'string') { return x } else { - return JSON_stringify(x) + return JSON_stringify(x, (_key: string, value: unknown) => + typeof value === 'bigint' ? value.toString() : value, + ) } }, parse: (x: string) => JSON_parse(x), diff --git a/packages/pglite/tests/types.test.ts b/packages/pglite/tests/types.test.ts index 05aba06ff..e79a5c8b6 100644 --- a/packages/pglite/tests/types.test.ts +++ b/packages/pglite/tests/types.test.ts @@ -144,7 +144,31 @@ describe('serialize', () => { ) }) - it('not blob', () => { - expect(() => types.serializers[17](1)).toThrow() + + it('json with bigint value', () => { + // BigInt values nested inside JSON objects must serialize to their string + // representation rather than throwing "Do not know how to serialize a BigInt" + // See https://github.com/electric-sql/pglite/issues/899 + expect(types.serializers[114]({ id: 1n })).toEqual('{"id":"1"}') + }) + + it('json with nested bigint in array', () => { + expect( + types.serializers[114]([{ id: 1n, name: 'a' }, { id: 2n, name: 'b' }]), + ).toEqual('[{"id":"1","name":"a"},{"id":"2","name":"b"}]') + }) + + it('jsonb with bigint value', () => { + expect(types.serializers[3802]({ id: 1n })).toEqual('{"id":"1"}') + }) + + it('json number values are unchanged', () => { + // Regular numbers must still serialize as numbers, not strings + expect(types.serializers[114]({ id: 1 })).toEqual('{"id":1}') + }) + + it('json string passthrough unchanged', () => { + // Pre-serialized JSON strings must pass through as-is + expect(types.serializers[114]('{"id":1}')).toEqual('{"id":1}') }) })