如何在Fastify中用Ajv验证逗号分隔查询字符串为数组?
解决Fastify中逗号分隔查询字符串数组的解析与验证问题
问题原因
Fastify默认使用qs库解析查询字符串,但默认配置不会自动将逗号分隔的字符串拆分为数组。因此userNo=1,2会被解析为单个字符串元素的数组['1,2'],而非预期的['1','2']。
解决方案
需要从查询字符串解析规则配置和Schema验证逻辑两方面调整,确保逗号分隔值被正确拆分并通过验证。
1. 开启Fastify的逗号分隔数组解析
在Fastify实例初始化时,配置querystring选项开启comma支持,让qs库自动拆分逗号分隔的数组值:
const fastify = Fastify({ querystring: { comma: true // 核心配置:开启逗号分隔数组解析 } });
该配置是全局生效的,所有查询字符串中的逗号分隔数组都会被正确拆分。
2. 优化Schema定义(保持验证严谨性)
你的现有Schema已经正确定义了userNo为字符串数组,可根据参数是否可选调整Partial的使用,让验证逻辑更清晰:
import { Type } from '@fastify/type-provider-typebox'; // 如果userNo是必填参数 export const userNoSchema = Type.Object({ userNo: Type.Array(Type.String()) }, { $id: 'userNo' }); // 如果userNo是可选参数 // export const userNoSchema = Type.Partial( // Type.Object({ userNo: Type.Array(Type.String()) }), // { $id: 'userNo' } // );
3. 保持Ajv编译器配置不变
你当前的@fastify/ajv-compiler配置无需修改,只要查询字符串被正确解析为数组,Ajv会自动完成数组类型的验证。确保使用的是@fastify/ajv-compiler的稳定版本即可。
完整可运行示例
import Fastify from 'fastify'; import fp from 'fastify-plugin'; import { Type } from '@fastify/type-provider-typebox'; import fstAjvCompiler from '@fastify/ajv-compiler'; // Schema定义 export const userNoSchema = Type.Partial( Type.Object({ userNo: Type.Array(Type.String()) }), { $id: 'userNo' } ); const getSchema = { querystring: Type.Ref(userNoSchema), response: { 200: Type.Object({ data: Type.Record(Type.String(), Type.String()) }) } }; // Fastify插件 export default fp((instance, options, done) => { instance.addSchema(userNoSchema); const factory = fstAjvCompiler(); const schemas = instance.getSchemas() as Parameters<typeof factory>[0]; const validator = factory(schemas, { customOptions: { keywords: ['instanceOf', 'example'] } }); instance.setValidatorCompiler(validator); // 注册测试路由 instance.get('/api/v1/users/', { schema: getSchema }, (request, reply) => { console.log(request.query.userNo); // 输出 ['1','2'] reply.send({ data: { status: 'success' } }); }); done(); }); // 初始化Fastify实例 const fastify = Fastify({ querystring: { comma: true } }); fastify.register(import('./your-plugin-file.js')); fastify.listen({ port: 3000 }, (err) => { if (err) throw err; console.log('Server running on http://127.0.0.1:3000'); });
验证测试
发送请求http://127.0.0.1:3000/api/v1/users/?userNo=1,2,此时request.query.userNo会被正确解析为['1','2'],且能通过Ajv的数组类型验证。
内容的提问来源于stack exchange,提问作者ZhiHan
相关产品推荐
相关产品推荐

