@rjsf/validator-ata 完全指南:为 react-jsonschema-form 接入 ata-validator 校验引擎
2026/9/21 22:51:38 网站建设 项目流程

@rjsf/validator-ata 完全指南:为 react-jsonschema-form 接入 ata-validator 校验引擎

【免费下载链接】react-jsonschema-formA React component for building Web forms from JSON Schema.项目地址: https://gitcode.com/gh_mirrors/re/react-jsonschema-form

@rjsf/validator-ata是 react-jsonschema-form(RJSF)生态中一个基于ata-validator)为主体骨架,结合packages/validator-ata的源码与配套的验证指南,完整讲解其公共 API(customizeValidatorcompileSchemaValidatorscreatePrecompiledValidator)、与 AJV8 校验器的差异、预编译校验(Precompiled Validator)工作流,以及底层实现原理,帮助你快速完成迁移、定制与排障。

一、它是什么:一行 import 完成的校验器替换

自 RJSF v5 起,校验实现已从Form组件中解耦,所有Form必须显式传入一个实现了ValidatorType<T, S, F>接口(定义于@rjsf/utils)的校验器实例。@rjsf/validator-ata正是这样一份实现,其公共 API 表面与 AJV8 校验包完全对齐,因此:

// 之前 import validator from '@rjsf/validator-ajv8'; // 之后 import validator from '@rjsf/validator-ata';

仅替换 import 即可让表单继续工作。文档明确承诺以下能力在两个包中行为一致:

  • customizeValidator()定制入口;
  • ValidatorType<T, S, F>类型接口;
  • 自定义格式(custom formats);
  • transformErrors错误变换;
  • customValidate自定义校验;
  • suppressDuplicateFiltering重复错误过滤。

从源码入口 packages/validator-ata/src/index.ts 可以看到,该包导出customizeValidatorcreatePrecompiledValidatorATAValidator类及全部类型,并以export default customizeValidator()作为默认导出,与 AJV8 包的默认导出形态一致。

配套的完整校验用法示例(liveValidatecustomValidatetransformErrorsnoHtml5ValidateextraErrors等)见仓库的验证文档,本文重点聚焦 validator-ata 自身的 API 与实现。

二、与 @rjsf/validator-ajv8 的差异

官方文档列出了四个关键差异,理解它们有助于评估迁移成本:

  1. 不接受 AJV 专属选项AjvClassajvFormatOptionsajvOptionsOverrides在 ata 版中均不可用。最接近的等价物是ataOptionsOverrides,它会被浅展开(spread)到默认的ata-validator选项之上。这一点在 types.ts 的类型注释中有明确说明:与 AJV 无对应映射的旋钮被有意省略。
  2. 格式集总是安装ata-validator自带格式集始终生效,没有 AJV 版那种通过ajvFormatOptions控制格式安装的开关。从 createAtaInstance.ts 的实现看,ata 实例构造时会无条件注册 RJSF 依赖的colordata-url两个内置格式(COLOR_FORMAT_REGEXDATA_URL_FORMAT_REGEX与 AJV8 包保持一致),再叠加用户传入的customFormats
  3. 错误参数被冻结ata-validatorerror.params是冻结(frozen)对象,因此 AJV8 版为配合ajv-i18n而做的"预引号处理"(pre-quote pass)不再需要。凡是采用原地修改message方式的本地化器(localizer)依然可以直接使用。对应实现见 validator.ts:localizer直接以原始 ata 错误数组为参数被调用。
  4. 预编译校验器同样受支持compileSchemaValidators/createPrecompiledValidator均可用。ata-validatorbundleStandalone输出被适配为预编译消费者期望的"校验函数映射"。错误输出与非预编译路径一致,包括:
    • 对 schema 形态的additionalProperties产生逐字段错误(需要ata-validator >= 0.17.4;当前仓库依赖^1.7.1,满足该要求,见 package.json);
    • 非法的anyOf与运行时路径一致,只在字段上报告单个错误;
    • 从 standalone(AOT)路径继承的约束:自定义格式必须是 RegExp 或预锚定(pre-anchored)的字符串模式,因为函数形式的检查器无法序列化进 bundle,会在编译期被拒绝。

三、类型体系

@rjsf/validator-ata导出了一组支撑上述 API 的 TypeScript 类型,完整定义见 packages/validator-ata/src/types.ts,核心包括:

类型说明
AtaFormatChecker(value: string) => boolean形状的自定义格式检查器,与ata-validatorformats选项对齐
SuppressDuplicateFilteringType'anyOf' \| 'oneOf' \| 'all' \| 'none',控制哪些关键字跳过重复错误过滤
Localizer接收ata-validatorValidationError列表并原地修改/替换消息的本地化函数(注意与 AJV 版的ErrorObject[]输入类型不同)
CustomValidatorOptionsTypecustomizeValidator()的选项映射,见下文第四节
CompiledValidateFunction预编译模块中单个校验函数的简化形态:(data: unknown) => boolean,并挂载errors属性
ValidatorFunctionsRecord<string, CompiledValidateFunction>,即预编译文件导出的校验函数映射

其中CustomValidatorOptionsType的字段与语义如下(types.ts):

  • additionalMetaSchemas?: readonly object[]:额外注册的 schema,用于跨 schema 的$ref解析,语义对应 AJV 的addMetaSchema/addSchema
  • customFormats?: Record<string, string \| RegExp \| AtaFormatChecker>:自定义格式检查器,值可以是函数、RegExp 或(会被编译为函数的)预锚定正则源码字符串;
  • ataOptionsOverrides?: ValidatorOptions:覆盖默认ata-validator选项,例如coerceTypesremoveAdditionalverboseabortEarly
  • extenderFn?: (validator: Validator) => Validator:对刚构造的Validator实例做额外设置的回调,允许返回不同实例;
  • suppressDuplicateFiltering?: SuppressDuplicateFilteringType:见下文。

四、customizeValidator():构建定制校验器

customizeValidator<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>( options?: CustomValidatorOptionsType, localizer?: Localizer, ): ValidatorType<T, S, F>

创建并返回给定定制选项下的ValidatorType实现。如果提供了localizer,它会被用来翻译底层ata-validator校验生成的错误消息。

4.1 选项详解

  • additionalMetaSchemas:用于跨 schema$ref解析的附加 schema。在 createAtaInstance.ts 中,这些 meta schema 会逐个调用validator.addSchema(meta)注册。
  • customFormats:自定义格式检查器。三种取值形态在 asFormatChecker 中被统一归一为(value: string) => boolean:函数直接透传,RegExp 包装成.test(value)调用,字符串被视为正则源码构造new RegExp(spec)
  • ataOptionsOverrides:展开到默认选项之上。默认选项ATA_CONFIG只有一项(createAtaInstance.ts):verbose: true。这是因为verbose会让错误对象保留parentSchema,而 RJSF 的错误转换器依赖它恢复字段标题(title);其余默认行为(等价于 AJV 的allErrors)由 ata 自身默认提供。
  • extenderFn:构造完Validator实例后立即调用,可在此接入第三方增强(类似 AJV 生态的ajv-errors/ajv-keywords),返回值支持替换原实例。
  • suppressDuplicateFiltering:控制anyOf/oneOf重复错误的过滤,取值语义如下表(该表亦适用于 AJV8 包):
行为
'none'(默认)anyOfoneOf的重复错误都被过滤
'anyOf'关闭anyOf的重复过滤;oneOf仍过滤
'oneOf'关闭oneOf的重复过滤;anyOf仍过滤
'all'关闭全部重复过滤,返回每个分支产生的每条错误

过滤逻辑的底层实现位于 processRawValidationErrors.ts 的filterDuplicateErrors:在非'all'模式下,对schemaPath中含/anyOf//oneOf/段的错误,凡是在该段之前前缀相同且消息相同的,只保留第一条。

4.2 localizer(本地化)

第二个参数localizer的类型为Localizer,即(errors?: null | ValidationError[]) => void。由于 ata 的error.params被冻结,AJV8 版为ajv-i18n准备的预引号处理无法照搬,但任何原地修改message的本地化函数都能直接工作。例如一个自定义俄语本地化器(对照 validation.md 中的 AJV 版示例,输入错误类型改为 ata 的ValidationError):

import { Form } from '@rjsf/core'; import { RJSFSchema } from '@rjsf/utils'; import { customizeValidator } from '@rjsf/validator-ata'; import type { ValidationError } from 'ata-validator'; function localize_ru(errors: null | ValidationError[] = []) { if (!(errors && errors.length)) return; errors.forEach((error) => { switch (error.keyword) { case 'pattern': error.message = 'должно соответствовать образцу "' + error.params.pattern + '"'; break; case 'required': error.message = 'поле обязательно для заполнения'; break; default: break; // 保持原始 message } }); } const schema: RJSFSchema = { type: 'string' }; const validator = customizeValidator({}, localize_ru); render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

要点:必须原地修改列表并自行覆盖所有需要处理的关键字分支。

4.3 组合使用示例

import { Form } from '@rjsf/core'; import { RJSFSchema } from '@rjsf/utils'; import { customizeValidator } from '@rjsf/validator-ata'; const schema: RJSFSchema = { type: 'string', format: 'phone-us', }; const validator = customizeValidator({ customFormats: { 'phone-us': /\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{4}$/, }, ataOptionsOverrides: { coerceTypes: true, // 允许类型强制转换 verbose: true, // 保留 parentSchema 供错误标题解析 }, suppressDuplicateFiltering: 'all', // 展示 anyOf/oneOf 所有分支错误 }); render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

五、预编译校验器:绕过 CSP 与启动期编译

预编译校验器(Precompiled Validator)的核心动机有三个:减小打包体积、通过跳过 schema 编译提升启动速度,以及在浏览器 Content Security Policy(CSP)禁止动态代码生成时避免运行时unsafe-eval。工作流分两步:

  1. compileSchemaValidators()把 schema 预编译为 CommonJS 模块文件;
  2. createPrecompiledValidator()把编译产物包装成ValidatorType交给Form

5.1 compileSchemaValidators():schema 预编译

compileSchemaValidators<S extends StrictRJSFSchema = RJSFSchema>( schema: S, output: string, options?: CustomValidatorOptionsType, ): void

schema编译进名为output的输出文件中,之后可作为预编译校验器加载。optionscustomizeValidator()接受同一组CustomValidatorOptionsType,用于影响编译时使用的 ata 校验器。

典型用法(官方推荐建一个compileYourSchema.js后用 node 运行):

const compileSchemaValidators = require('@rjsf/validator-ata/compileSchemaValidators').default; const yourSchema = require('path_to/yourSchema'); // 若 schema 是 js 文件 compileSchemaValidators(yourSchema, 'path_to/yourCompiledSchema.js');

带定制选项的版本:

const { compileSchemaValidators } = require('@rjsf/validator-ata'); const yourSchema = require('path_to/yourSchema.json'); // 若 schema 是 json 文件 const options = { additionalMetaSchemas: [/* 需要注册的附加 meta schema */], customFormats: { 'phone-us': /\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{4}$/, }, ataOptionsOverrides: { verbose: true, }, }; compileSchemaValidators(yourSchema, 'path_to/yourCompiledSchema.js', options);

然后执行:

node compileYourSchema.js

实现细节:该函数先调用compileSchemaValidatorsCode(schema, options)生成模块代码,再用fs.writeFileSync(output, moduleCode)落盘(compileSchemaValidators.ts)。包入口已通过 package.json 的exports暴露./compileSchemaValidators子路径(package.json),同时支持require(CJS)与import(ESM)。

重要限制:通过options.customFormats传入的自定义格式必须是RegExp 或预锚定的字符串模式。函数检查器无法序列化进 standalone bundle,会在编译期被拒绝(抛出明确错误)。

该限制的源码依据在 compileSchemaValidatorsCode.ts:函数形式会被Function#toString序列化,而转译器、压缩器与覆盖率工具会改写函数体并留下生成模块中不存在的引用,因此只有 RegExp/字符串模式能被可靠内嵌。

5.2 createPrecompiledValidator():加载预编译产物

createPrecompiledValidator<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>( validateFns: ValidatorFunctions, rootSchema: S, localizer?: Localizer, suppressDuplicateFiltering?: SuppressDuplicateFilteringType, ): ValidatorType<T, S, F>
  • validateFns:由compileSchemaValidators()生成的预编译文件经 import 得到的函数映射对象;
  • rootSchema:编译时使用的同一个根 schema;
  • localizer:可选,用于翻译 ataValidationError列表;
  • suppressDuplicateFiltering:可选,语义与customizeValidator()相同(见 4.1 表格)。

Form中使用:

import { useMemo } from 'react'; import Form, { FormProps } from '@rjsf/core'; // 或任意主题包 import { createPrecompiledValidator } from '@rjsf/validator-ata'; import yourSchema from 'path_to/yourSchema'; // 必须与编译时是同一文件 import * as precompiledValidatorFns from 'path_to/yourCompiledSchema'; function MyForm(props: Omit<FormProps, 'validator' | 'schema'>) { // 记忆化校验器,避免重复渲染时重建 const validator = useMemo( () => createPrecompiledValidator(precompiledValidatorFns, yourSchema), [precompiledValidatorFns, yourSchema], ); return <Form schema={yourSchema} validator={validator} {...props} />; }

注意:validateFns必须是compileSchemaValidators()产物的 import 结果。若传入的 schema 与构造ATAPrecompiledValidator时的根 schema 不一致,ensureSameRootSchema会抛出错误;若映射中找不到对应 schema 的校验函数,getValidator同样会抛错(precompiledValidator.ts)。

5.3 动态预编译:compileSchemaValidatorsCode

对于"按请求动态预编译"的高级场景,可以改用compileSchemaValidatorsCode(schema, options)——它与compileSchemaValidators逻辑相同,但不写文件,直接返回生成的代码字符串

import { compileSchemaValidatorsCode } from '@rjsf/validator-ata/compileSchemaValidators'; const code = compileSchemaValidatorsCode(schema, options);

在浏览器端使用该代码时,需要为生成代码中的运行时依赖提供替代实现(其机制与 AJV 包的动态预编译流程一致,可参考 validation.md 中evaluateValidator与替换映射的完整示例)。

六、源码级原理:ATAValidator 如何工作

customizeValidator()的实现非常薄(customizeValidator.ts):它只是new ATAValidator<T, S, F>(options, localizer)。真正的逻辑都在ATAValidator类中(validator.ts),理解以下几点可以解释文档中大部分行为差异:

6.1 与 AJV 的架构差异:schema 绑定 vs 实例注册表

AJV 是"单实例 + schema 注册表"模型;而ata 是 schema 绑定(schema-bound)模型,每个 schema 对应一个Validator实例。因此ATAValidator内部维护了一个按 schema id 索引的缓存:private readonly validators = new Map<string, { validator: Validator; schema: object }>()。缓存键优先取 schema 的$idID_KEY),否则用hashForSchema生成的哈希(validator.ts)。

当 RJSF 传入新的根 schema 时,handleSchemaUpdate会把根 schema 注册进 ata 的 schema 集合,使子 schema 校验时$ref仍能解析到根级definitions(validator.ts)。reset()方法清空缓存与根 schema 记账,供 RJSF 测试框架在多次运行间刷新状态。

6.2 防篡改克隆:cloneForValidation

ata 的默认值应用器在校验过程中会把default写回传入的数据对象。而 RJSF 在解析oneOf/anyOf分支时会通过isValid反复探测同一份数据,被篡改的探测结果会改变后续答案。为此ATAValidator在每次校验前用structuredClone深拷贝数据(validator.ts),以保持 AJV 默认具备的引用纯净性。

6.3 错误处理管线

无论运行时路径还是预编译路径,最终都汇入 processRawValidationErrors.ts 的同一套管线:

  1. transformRJSFValidationErrors将 ata 错误结构化为 RJSF 的RJSFValidationError(ata 错误字段与 AJV 同名:instancePathkeywordparamsschemaPathparentSchemamessage,因此转换是结构性的),并依据 uiSchema/parentSchema/根 schema 中的title替换消息中的属性名;
  2. filterDuplicateErrorssuppressDuplicateFiltering折叠anyOf/oneOf重复错误;
  3. 追加 schema 编译错误(若存在)、调用transformErrors
  4. toErrorSchema构建errorSchema
  5. 若有customValidate,先getDefaultFormState补齐默认值,再合并用户错误。

这也印证了文档中的承诺:customValidatetransformErrorssuppressDuplicateFiltering等能力在两个校验包中行为一致。

七、迁移速查与注意事项

把现有 AJV8 校验器迁移到 validator-ata 时,按以下清单自查:

  1. 替换 import@rjsf/validator-ajv8@rjsf/validator-ata;预编译工具路径对应改为@rjsf/validator-ata/compileSchemaValidators
  2. 改写选项名ajvOptionsOverridesataOptionsOverrides;删除AjvClassajvFormatOptions(ata 格式集始终安装,无需开关)。
  3. 检查格式定义:运行时路径的customFormats支持函数/RegExp/字符串三种形态;预编译路径只接受 RegExp 或预锚定字符串,函数会在编译期直接报错。
  4. 检查本地化器:只要你的 localizer 是原地修改message,无需改动即可继续使用;无需为ajv-i18n做预引号处理。
  5. 确认版本前提:若使用 schema 形态的additionalProperties并期望逐字段错误,需保证ata-validator >= 0.17.4(当前仓库锁定^1.7.1)。
  6. 验证错误输出:非法的anyOf只报告字段级单条错误,与运行时路径一致;如需查看每个分支的全部错误,使用suppressDuplicateFiltering: 'all'

如果需要进一步了解liveValidatecustomValidatetransformErrorsextraErrors、错误列表模板等与校验相关的完整表单用法,可继续阅读仓库的验证文档;所有 API 的最终权威定义位于 packages/validator-ata/src 目录,测试用例可参考 packages/validator-ata/test 下的validator.test.tscustomizeValidator.test.tsprecompiledValidator.test.ts等文件。

【免费下载链接】react-jsonschema-formA React component for building Web forms from JSON Schema.项目地址: https://gitcode.com/gh_mirrors/re/react-jsonschema-form

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询