如何通过JSON Schema确保JSON数组内对象按指定属性字母序排列?
关于用JSON Schema验证数组对象排序的问题
好问题!先直接给你结论:标准JSON Schema(Draft 2020-12及更早版本)本身不支持直接验证数组元素的排序规则,不过我们可以通过验证库的自定义扩展能力来实现这个需求——主流的JSON Schema验证工具(比如Ajv)都支持添加自定义关键词来实现这类逻辑。
为什么标准JSON Schema做不到?
标准JSON Schema的设计目标是验证数据的结构、类型和单个值的约束,它并不包含用于检查数组元素之间顺序关系的原生关键词。items这类关键词只负责验证数组里的每个元素是否符合指定的结构,完全不关心元素的排列顺序。
实现方案:用自定义关键词扩展验证逻辑
以常用的Ajv库为例,我们可以添加自定义关键词(比如orderedBy),编写自定义验证函数来检查数组是否按照指定属性的升序/降序排列。
步骤1:定义带自定义关键词的JSON Schema
修改你提供的Schema,添加自定义关键词来指定排序规则:
{ "type": "object", "properties": { "cities": { "type": "array", "items": { "type": "object", "properties": { "shortName": { "type": "string" }, "name": { "type": "string" }, "showInMap": { "type": "boolean" }, "active": { "type": "boolean" } }, "required": [ "shortName" ] }, // 自定义关键词:指定按shortName升序排列 "orderedBy": { "property": "shortName", "order": "asc" } } } }
步骤2:在Ajv中注册自定义验证逻辑
在Node.js环境下,你可以这样注册自定义关键词并验证数据:
const Ajv = require('ajv'); const ajv = new Ajv(); // 注册自定义关键词"orderedBy" ajv.addKeyword('orderedBy', { type: 'array', validate: function(schema, data) { const { property, order = 'asc' } = schema; // 遍历数组,检查相邻元素的指定属性是否符合排序规则 for (let i = 0; i < data.length - 1; i++) { const current = data[i][property]; const next = data[i+1][property]; if (order === 'asc' && current > next) { return false; } if (order === 'desc' && current < next) { return false; } } return true; }, // 可选:添加错误信息提示 errors: true, messages: { en: "Array must be ordered by {{property}} in {{order}} order" } }); // 加载你的Schema const schema = require('./your-schema.json'); const validate = ajv.compile(schema); // 验证有效示例 const validData = { "cities": [ { "shortName": "LD", "name": "London", "showInMap": true, "active": false }, { "shortName": "MO", "name": "Moscow", "showInMap": false, "active": false }, { "shortName": "NY", "name": "New York", "showInMap": true, "active": true } ] }; console.log(validate(validData)); // 输出: true // 验证无效示例 const invalidData = { "cities": [ { "shortName": "NY", "name": "New York", "showInMap": true, "active": true }, { "shortName": "LD", "name": "London", "showInMap": true, "active": false }, { "shortName": "MO", "name": "Moscow", "showInMap": false, "active": false } ] }; console.log(validate(invalidData)); // 输出: false console.log(validate.errors); // 会显示排序错误的提示信息
注意事项
- 自定义关键词是依赖于具体验证库的,不同的库(比如tv4、Zod)的扩展方式会有所不同,上面的例子仅适用于Ajv。
- 如果你的使用场景无法依赖第三方库的扩展能力,那可能需要在Schema验证之后,额外添加一层代码逻辑来检查数组的排序。
内容的提问来源于stack exchange,提问作者MarcelHodan
相关产品推荐
相关产品推荐

