如何通过JSON Schema确保对象属性仅出现一次?
如何限制JSON Schema中对象属性仅出现一次?
问题场景
你编写了如下JSON Schema,希望确保singleton属性在JSON对象中仅出现一次:
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "singleton": { "type": "string" } } }
但包含重复singleton属性的JSON文件,依然能通过Python的check-jsonschema工具校验:
{ "singleton": "ok", "singleton": "not ok" }
你想知道:是否能在Schema中直接限制属性出现次数?有没有类似XML Schema里minOccurs/maxOccurs的机制?
解答
首先明确两个核心事实:
- JSON解析器的默认行为:绝大多数标准JSON解析器(包括Python内置的
json模块)处理重复属性时,会自动保留最后一个属性的值、丢弃前面的重复项。这意味着当check-jsonschema开始校验时,重复属性已经被合并成单个属性,自然无法检测到重复。 - JSON Schema本身的限制:JSON Schema规范中没有类似XML Schema的
minOccurs/maxOccurs机制来直接控制对象属性的出现次数——它的校验逻辑基于解析后的对象结构,而非原始JSON文本。
要解决这个问题,可靠的方案是在JSON解析阶段就拦截重复属性,再进行Schema校验。以下是Python中的实现示例:
import json from jsonschema import validate # 自定义钩子函数,检测重复键 def detect_duplicate_keys(pairs): seen_keys = set() for key, value in pairs: if key in seen_keys: raise ValueError(f"发现重复属性: {key}") seen_keys.add(key) yield key, value # 示例JSON文本 json_content = '''{ "singleton": "ok", "singleton": "not ok" }''' try: # 解析时检测重复键 parsed_data = json.loads(json_content, object_pairs_hook=detect_duplicate_keys) except ValueError as e: print(f"JSON格式错误: {e}") else: # 执行Schema校验 target_schema = { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "singleton": {"type": "string"} } } validate(instance=parsed_data, schema=target_schema) print("JSON校验通过")
这个方案的逻辑是:利用json.loads的object_pairs_hook参数,在解析键值对的过程中跟踪已出现的属性名,一旦发现重复就抛出错误,从源头阻止重复属性进入校验环节。
内容的提问来源于stack exchange,提问作者Jorge D
相关产品推荐
相关产品推荐

