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

Fastify+Yup验证报错:schema.validateSync不是函数,需兼顾Swagger生成

解决Fastify中Yup验证与Swagger文档共存的问题

问题根源

你遇到的schema.validateSync is not a function错误,是因为validatorCompiler里拿到的schema是JSON Schema对象,不是Yup实例——JSON Schema本身没有validateSync方法。而直接用Yup对象替换schema里的params时,Fastify的Swagger插件只识别JSON Schema格式,所以无法生成文档。

解决方案

要同时满足Yup验证和Swagger文档生成,核心是让路由配置同时提供Swagger所需的JSON Schema,以及Yup验证所需的实例。下面提供两种可行方案:

方案一:手动维护双Schema

在路由配置中,JSON Schema用于生成Swagger文档,单独定义的Yup Schema用于验证逻辑,在validatorCompiler中根据请求部分(params/query/body等)匹配对应的Yup实例:

const yup = require("yup");

const yupOptions = {
  strict: false,
  abortEarly: false,
  stripUnknown: true,
  recursive: true,
};

async function isUsernameAvailable(fastify: any, _options: Object) {
  const users = fastify.mongo.db.collection("users");

  // 1. 定义Yup验证Schema
  const paramsYupSchema = yup.object({
    username: yup.string().lowercase().max(12).min(1).required()
  });

  fastify.get(
    "/api/v1/onboarding/isUsernameAvailable/:username",
    {
      schema: {
        // 2. 定义JSON Schema用于Swagger生成
        params: {
          type: "object",
          properties: {
            username: { type: "string", maxLength: 12, minLength: 1, description: "用户名" },
          },
          required: ["username"],
        },
        response: {
          200: {
            type: "object",
            properties: {
              available: {
                type: "boolean",
                description: "用户名是否可用",
              },
            },
          },
        },
      },
      validatorCompiler: ({ httpPart }: any) => {
        // 3. 根据请求部分选择对应的Yup Schema
        let yupSchema;
        switch (httpPart) {
          case "params":
            yupSchema = paramsYupSchema;
            break;
          // 如果有query/body,在这里添加对应分支
          default:
            return (data: any) => ({ value: data });
        }

        return function (data: any) {
          try {
            const result = yupSchema.validateSync(data, yupOptions);
            return { value: result };
          } catch (e) {
            return { error: e };
          }
        };
      },
    },

    async (request: any, _reply: any) => {
      // 这里的request.params已经是Yup处理后的(比如转成小写)
      const { username } = request.params;
      const foundNUsernames = await users.countDocuments(
        { username },
        { limit: 1 }
      );
      const available: boolean = foundNUsernames === 0;
      return { available };
    }
  );
}

export { isUsernameAvailable };

方案二:自动转换Yup到JSON Schema

使用yup-to-json-schema工具,将Yup Schema自动转换成JSON Schema,避免手动维护双份规则:

  1. 安装依赖:
npm install yup-to-json-schema
  1. 修改代码:
const yup = require("yup");
const yupToJsonSchema = require("yup-to-json-schema");

const yupOptions = {
  strict: false,
  abortEarly: false,
  stripUnknown: true,
  recursive: true,
};

async function isUsernameAvailable(fastify: any, _options: Object) {
  const users = fastify.mongo.db.collection("users");

  // 1. 只定义Yup Schema
  const paramsYupSchema = yup.object({
    username: yup.string().lowercase().max(12).min(1).required()
  });

  // 2. 自动转换为JSON Schema
  const paramsJsonSchema = yupToJsonSchema(paramsYupSchema);

  fastify.get(
    "/api/v1/onboarding/isUsernameAvailable/:username",
    {
      schema: {
        // 3. 用转换后的JSON Schema生成Swagger
        params: paramsJsonSchema,
        response: {
          200: {
            type: "object",
            properties: {
              available: {
                type: "boolean",
                description: "用户名是否可用",
              },
            },
          },
        },
      },
      validatorCompiler: ({ httpPart }: any) => {
        // 4. 直接用Yup Schema验证
        let yupSchema;
        switch (httpPart) {
          case "params":
            yupSchema = paramsYupSchema;
            break;
          default:
            return (data: any) => ({ value: data });
        }

        return function (data: any) {
          try {
            const result = yupSchema.validateSync(data, yupOptions);
            return { value: result };
          } catch (e) {
            return { error: e };
          }
        };
      },
    },

    async (request: any, _reply: any) => {
      const { username } = request.params;
      const foundNUsernames = await users.countDocuments(
        { username },
        { limit: 1 }
      );
      const available: boolean = foundNUsernames === 0;
      return { available };
    }
  );
}

export { isUsernameAvailable };

注意事项

  • 方案二的自动转换可能无法覆盖Yup的所有高级规则(比如自定义验证器),如果有特殊逻辑,建议用方案一手动补充JSON Schema的描述。
  • 无论哪种方案,validatorCompiler里都要确保拿到的是Yup实例,而不是JSON Schema对象,这样才能调用validateSync。

内容的提问来源于stack exchange,提问作者Bill

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:42:22