深入理解Ajv中的严格模式(Strict Mode)
ajv 项目地址: https://gitcode.com/gh_mirrors/ajv/ajv
什么是Ajv严格模式
Ajv(Another JSON Schema Validator)的严格模式是一种增强的验证机制,旨在防止JSON Schema中出现意外行为或静默忽略的错误。严格模式不会改变任何验证结果,但会使某些不符合严格要求的模式无效,并根据配置抛出异常或记录警告。
为什么需要严格模式
JSON Schema规范本身非常宽松,允许许多元素被静默忽略或存在歧义。这种设计虽然提高了跨平台兼容性,但也带来了几个问题:
- 同一模式在不同平台可能产生不同验证结果
- 关键字拼写错误会被静默忽略,难以发现
- 某些组合可能导致意外行为
严格模式通过强制实施一系列限制,帮助开发者编写更明确、更可靠的JSON Schema。
严格模式的主要特性
1. 禁止被忽略的关键字
未知关键字处理
默认情况下,Ajv在遇到未知关键字时会失败。开发者可以通过以下方式显式定义允许的关键字:
ajv.addKeyword("allowedKeyword")
// 或批量添加
ajv.addVocabulary(["allowed1", "allowed2"])
特殊关键字处理
additionalItems
:当items
不存在或不是数组时默认被忽略if/then/else
:当缺少对应关键字时默认被忽略contains
相关关键字:当contains
不存在时默认被忽略
严格模式下,这些情况都会导致编译失败。
2. 防止意外验证
属性与模式属性重叠
JSON Schema允许properties
和patternProperties
同时应用于同一属性,这可能导致意外行为。严格模式默认禁止这种情况。
必需的未定义属性
启用strictRequired
选项后,Ajv会检查required
中列出的属性是否在properties
中定义。
未约束的元组
对于定义为元组的数组模式(items
为数组),严格模式要求必须定义minItems
或additionalItems
/maxItems
。
3. 严格的类型检查
联合类型限制
严格模式下,type
关键字不允许使用多类型(除包含null
的情况)。应使用anyOf
代替:
// 不允许
{ type: ["string", "number"] }
// 允许
{
anyOf: [
{ type: "string" },
{ type: "number" }
]
}
矛盾类型检测
严格模式会检测并禁止类型定义中的矛盾,例如:
{
type: "object",
anyOf: [
{type: "array"} // 与object类型矛盾
]
}
要求适用类型
严格模式要求在使用properties
或required
时必须明确指定type: "object"
。
4. 严格的数字验证
默认情况下,严格模式会使{"type": "number"}
或"integer"
的验证对Infinity
和NaN
失败。
严格模式的配置选项
严格模式可以通过多种方式进行配置:
- 全局开关:
strict: true/false/"log"
- 单独选项:
strictSchema
:控制是否禁止被忽略的关键字strictRequired
:检查必需的未定义属性strictTuples
:检查未约束的元组strictTypes
:控制类型相关严格检查strictNumbers
:控制数字验证严格性
实际应用建议
- 对于新项目,建议始终启用严格模式
- 在迁移现有项目时,可以逐步启用各个严格选项
- 使用TypeScript时,
JSONSchemaType<T>
可以帮助避免许多严格模式会捕获的错误 - 对于需要灵活性的场景,可以单独关闭某些严格选项
总结
Ajv的严格模式是一组强大的工具,可以帮助开发者编写更健壮、更明确的JSON Schema。通过理解并合理配置各种严格选项,可以在灵活性和严谨性之间找到最佳平衡点,从而提高数据验证的可靠性。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考