如何扩展AJV支持自定义类型?遇Schema验证报错求助
解决AJV扩展自定义类型DocumentReference的报错问题
这个报错的核心原因很明确:AJV默认只认JSON Schema标准定义的类型(比如string、number、object这些),当你在schema里用了自定义的DocumentReference类型时,AJV会判定这是无效的类型值,所以抛出了类型不匹配的错误。而且你还要兼顾Python的jsonschema也能验证这个类型,得做双向兼容的配置才行。
下面是具体的解决步骤:
1. 在AJV中注册自定义类型
你需要通过AJV的addKeyword来扩展支持自定义类型,这里直接针对type关键字做处理,同时保留自定义校验逻辑:
const Ajv = require('ajv'); const ajv = new Ajv(); // 注册自定义类型DocumentReference的校验规则 ajv.addKeyword({ keyword: 'type', // 处理schema里的类型数组(比如["DocumentReference"]) modifySchema: (schema) => { // 如果是数组类型包含自定义类型 if (Array.isArray(schema.type)) { const hasCustomType = schema.type.includes('DocumentReference'); if (hasCustomType) { // 保留标准类型,同时把自定义类型替换为基础类型(假设你的DocumentReference是字符串格式) schema.type = schema.type.filter(t => t !== 'DocumentReference').concat('string'); // 标记需要做自定义校验 schema.isDocumentReference = true; } } // 如果是单独的自定义类型 else if (schema.type === 'DocumentReference') { schema.type = 'string'; schema.isDocumentReference = true; } }, // 实现具体的自定义类型校验逻辑 validate: (schema, data) => { if (schema.isDocumentReference) { // 这里写你的DocumentReference校验规则,比如检查格式是否符合要求 // 示例:校验是否是带特定前缀的字符串 return typeof data === 'string' && /^doc-ref:[a-f0-9-]+$/.test(data); } return true; }, errors: false // 如果需要自定义错误提示,可以设为true并补充error方法 });
2. 确保Python jsonschema的兼容性
Python端的jsonschema同样不认识自定义类型,你需要扩展校验器来支持:
import jsonschema from jsonschema import validators, Draft202012Validator def extend_document_reference_validator(validator_class): validate_properties = validator_class.VALIDATORS["properties"] def validate_doc_ref(validator, schema, instance, schema_path): if schema.get("isDocumentReference"): # 和前端保持一致的校验逻辑 if not isinstance(instance, str) or not instance.startswith("doc-ref:"): yield jsonschema.ValidationError( f"{instance} 不是有效的DocumentReference格式" ) # 继续执行其他属性校验 yield from validate_properties(validator, schema, instance, schema_path) return validators.extend( validator_class, {"properties": validate_doc_ref} ) # 创建扩展后的校验器 DocRefValidator = extend_document_reference_validator(Draft202012Validator)
这样你的schema可以同时兼容前后端校验,比如写type: ["DocumentReference", "string"]或者单独的type: "DocumentReference"都没问题。
3. 可选:调整Schema写法兼容标准校验器
如果不想修改校验器,也可以用oneOf来包装自定义类型和标准类型,不过还是需要配合自定义关键字标记:
{ "properties": { "allow": { "properties": { "custom_signature": { "oneOf": [ {"type": "DocumentReference"}, {"type": "string"} ], "isDocumentReference": true } } } } }
关键注意点
- 前后端的自定义类型校验逻辑必须完全一致,比如DocumentReference的格式规则(是否是字符串、有没有特定前缀/结构)要统一。
- 如果你的DocumentReference是对象类型,只需要把校验逻辑里的类型判断改成
typeof data === 'object'并检查对象的属性即可。
内容的提问来源于stack exchange,提问作者Elon Salfati
相关产品推荐
相关产品推荐

