-
Notifications
You must be signed in to change notification settings - Fork 331
Open
Description
Environment
- postgres: 3.4.0
- drizzle-orm: 0.30.0
- PostgreSQL: 15
Issue
When Drizzle ORM passes pre-stringified JSONB values, postgres-js stringifies them again, causing double-encoding.
// Drizzle passes: '{"foo":"bar"}'
// postgres-js serializes to: '"{\\"foo\\":\\"bar\\"}"'
// PostgreSQL stores: string instead of jsonb objectRoot cause
postgres-js assumes all JSONB values need serialization:
// src/types.js
json: {
to: 114,
from: [114, 3802], // 3802 = jsonb
serialize: x => JSON.stringify(x),
parse: x => JSON.parse(x)
}However, ORMs like Drizzle pre-process values:
// Drizzle's PgJsonb.mapToDriverValue()
override mapToDriverValue(value: T['data']): string {
return JSON.stringify(value); // Already stringified
}Result: JSON.stringify(JSON.stringify(value))
Reproduction
const { drizzle } = require('drizzle-orm/postgres-js')
const { pgTable, text, jsonb } = require('drizzle-orm/pg-core')
const postgres = require('postgres')
const client = postgres('postgresql://...')
const db = drizzle(client)
const test = pgTable('test', {
id: text('id').primaryKey(),
data: jsonb('data')
})
await db.insert(test).values({ id: '1', data: { foo: 'bar' } })
// SELECT jsonb_typeof(data) FROM test;
// Expected: "object"
// Actual: "string"Workaround
Override type configuration:
const client = postgres(url, {
types: {
json: {
to: 114,
from: [114, 3802],
serialize: x => x, // Pass through
parse: x => JSON.parse(x)
}
}
})Suggestion
Check if value is already a string:
json: {
to: 114,
from: [114, 3802],
serialize: x => typeof x === 'string' ? x : JSON.stringify(x),
parse: x => JSON.parse(x)
}This works for both ORM and direct usage scenarios.
Impact
Affects all ORMs that pre-process JSONB values (Drizzle, Prisma, TypeORM).
Related
hilja
Metadata
Metadata
Assignees
Labels
No labels