如何在JSON Schema中验证属性数量并禁止重复属性
首先得给你明确一个关键背景:标准的JSON解析器会自动处理重复键——绝大多数解析器会保留最后一次出现的键值对,直接丢弃前面的。这就导致当你的JSON走到Schema验证这一步时,已经被转换成了只有单个name属性的对象,所以你的现有Schema自然会判定它有效。
要实现“拒绝重复键”的需求,你得跳出标准JSON Schema的局限,这里有几个实用的方案:
1. 先做原始JSON文本的重复键检查(最可靠)
因为标准JSON Schema是基于解析后的JSON对象工作的,所以最直接的办法是在解析JSON之前,先对原始字符串做一遍扫描,检查有没有重复的键。
举个简单的JavaScript示例(你可以根据自己用的语言做类似实现):
function hasDuplicateKeys(rawJson) { const seenKeys = new Set(); // 这个正则适用于简单JSON场景,如果键包含特殊字符可能需要调整 const keyMatcher = /"([^"]+)":/g; let matchResult; while ((matchResult = keyMatcher.exec(rawJson)) !== null) { const key = matchResult[1]; if (seenKeys.has(key)) { return true; } seenKeys.add(key); } return false; } // 使用方式 const badJson = '{ "name": "W", "name": "W" }'; if (hasDuplicateKeys(badJson)) { console.log("提交的JSON包含重复键,验证失败"); } else { // 继续执行标准的JSON Schema验证 }
这种方式的好处是直接在源头拦截问题,不需要依赖Schema的特殊扩展,兼容性拉满。
2. 使用支持原始语法验证的Schema工具/扩展
有些第三方的JSON Schema验证库提供了扩展能力,可以直接检查原始JSON文本中的重复键。比如部分工具会在解析前先扫描整个JSON字符串,一旦发现重复键就直接抛出错误,不用进入后续的Schema验证流程。如果你项目中已经在用特定的验证工具,可以去查一下它的文档,看看有没有相关的配置选项。
关于标准JSON Schema的说明
这里要划重点:从draft-04到最新的draft-2020-12,标准JSON Schema本身都不支持检测重复键。因为Schema的验证对象是解析后的JSON值,而解析后的对象是不可能存在重复键的——解析器已经帮你“抹平”了这个问题。所以只靠标准Schema是做不到这个需求的,必须结合额外的检查步骤。
总结一下,最推荐的就是先做原始文本的重复键检测,再走Schema验证,这样就能确保只有完全符合要求的JSON才能通过验证。
内容的提问来源于stack exchange,提问作者a.cayzer

