SvelteKit+Prisma+PostgreSQL:单表非POJO序列化错误排查
问题原因
报错核心是parish_rate字段的返回值不是SvelteKit序列化机制支持的普通JavaScript对象/原生类型。
结合PostgreSQL+Prisma的常见场景,大概率是parish_tax表的parish_rate字段在数据库中是NUMERIC/DECIMAL类型,Prisma默认会将这类字段序列化为Decimal对象(来自@prisma/client的内置类),而非原生的number或string。SvelteKit要求load函数返回的数据必须是可JSON序列化的POJO(Plain Old JavaScript Object),Decimal对象属于非标准类型,因此触发序列化错误。
而companies和barges表的字段类型(比如INT/VARCHAR等)会被Prisma转换为原生JS类型,所以能正常加载。
解决方案
方案1:查询时手动转换字段类型
在findMany查询后,把Decimal对象转成原生的number或string:
export const load = (async () => { const parishTaxRaw = await prisma.parish_tax.findMany(); const parish_tax = parishTaxRaw.map(item => ({ ...item, // 转number(注意精度溢出风险)或转string parish_rate: Number(item.parish_rate) })); const response = { companies: await prisma.companies.findMany(), barges: await prisma.barges.findMany(), parish_tax }; return { feed: response }; }) satisfies PageServerLoad;
方案2:修改Prisma Schema映射类型
如果业务允许,可以在Prisma schema中把parish_rate直接映射为JS的Float或String类型,避免手动转换:
model parish_tax { // 其他字段定义... parish_rate Float @db.Decimal(precision: 10, scale: 2) // 若担心精度问题,改用String: // parish_rate String @db.Decimal(precision: 10, scale: 2) }
修改后需要重新生成Prisma客户端:
npx prisma generate
注意:用
Float映射DECIMAL时,如果字段精度超过JS Number的安全范围(大于2^53),会丢失精度,这种场景建议用String映射。
方案3:自定义SvelteKit序列化规则(不推荐优先使用)
通过SvelteKit的hooks.server.ts自定义序列化逻辑,让框架能识别Decimal对象:
import type { Handle } from '@sveltejs/kit'; import { Decimal } from '@prisma/client/runtime/library'; export const handle: Handle = async ({ event, resolve }) => { const response = await resolve(event, { serializeData: (data) => { return JSON.stringify(data, (key, value) => { if (value instanceof Decimal) { return value.toString(); // 或转Number } return value; }); } }); return response; };
内容的提问来源于stack exchange,提问作者cdwhiteiv
相关产品推荐
相关产品推荐

