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

如何扩展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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:41:12