You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TRPC中自定义JSON序列化?解决BigInt校验失败问题

在TRPC中自定义JSON序列化处理BigInt问题

你之前全局修改BigInt.prototype.toJSON的方式会导致所有BigInt被转成字符串,TRPC传输后Zod校验时因为期望BigInt类型而失败。正确的做法是在TRPC层面自定义序列化逻辑,而非全局污染原型链,下面是两种可行方案:

方案一:使用superjson(推荐)

superjson是TRPC官方推荐的序列化工具,原生支持BigInt、Date等类型的双向转换,无需手动处理递归:

  1. 安装依赖
npm install superjson
  1. 配置TRPC服务端
    在创建TRPC router时指定transformer为superjson:
import { initTRPC } from '@trpc/server';
import superjson from 'superjson';

const t = initTRPC.create({
  transformer: superjson,
});

export const router = t.router;
export const publicProcedure = t.procedure;
  1. 配置TRPC客户端
    在客户端初始化时同步使用superjson:
import { createTRPCReact } from '@trpc/react-query';
import type { AppRouter } from '../server';
import superjson from 'superjson';

export const trpc = createTRPCReact<AppRouter>();

// 初始化client的示例(React项目)
export function useTRPC() {
  return trpc.useClient({
    url: '/api/trpc',
    transformer: superjson,
  });
}
  1. Zod校验适配
    直接使用z.bigint()定义校验规则即可,superjson会自动把传输过程中的字符串转回BigInt:
import { z } from 'zod';

const getByIdProcedure = publicProcedure
  .input(z.object({
    userId: z.bigint(),
  }))
  .query(({ input }) => {
    // input.userId 是BigInt类型,可直接使用
    return { userId: input.userId };
  });

方案二:手动实现自定义序列化器

如果不想引入额外依赖,可以手动编写TRPC的transformer函数,通过标记法处理BigInt:

import { initTRPC } from '@trpc/server';

const t = initTRPC.create({
  transformer: {
    // 序列化:把BigInt转成带标记的对象
    serialize: (data) => {
      const replacer = (_key: string, value: unknown) => {
        if (typeof value === 'bigint') {
          return { __type: 'bigint', value: value.toString() };
        }
        return value;
      };
      return JSON.stringify(data, replacer);
    },
    // 反序列化:把带标记的对象转回BigInt
    deserialize: (data) => {
      const reviver = (_key: string, value: unknown) => {
        if (
          typeof value === 'object' &&
          value !== null &&
          '__type' in value &&
          (value as any).__type === 'bigint' &&
          'value' in value
        ) {
          return BigInt((value as any).value);
        }
        return value;
      };
      return JSON.parse(data, reviver);
    },
  },
});

这种方式需要自己处理数据的递归遍历,适合对依赖体积有严格要求的场景。


内容的提问来源于stack exchange,提问作者Luis Angel Perez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 20:55:20