JSON Schema - 需要所有属性
Posted
技术标签:
【中文标题】JSON Schema - 需要所有属性【英文标题】:JSON Schema - require all properties 【发布时间】:2015-09-01 07:08:45 【问题描述】:JSON Schema 中的required
字段
JSON Schema 具有 properties
、required
和 additionalProperties
字段。例如,
"type": "object",
"properties":
"elephant": "type": "string",
"giraffe": "type": "string",
"polarBear": "type": "string"
,
"required": [
"elephant",
"giraffe",
"polarBear"
],
"additionalProperties": false
将验证 JSON 对象,例如:
"elephant": "Johnny",
"giraffe": "Jimmy",
"polarBear": "George"
但如果属性列表不是完全正确 elephant, giraffe, polarBear
,则会失败。
问题
我经常将properties
的列表复制粘贴到required
的列表中,当由于拼写错误和其他愚蠢的错误导致列表不匹配时,我会遇到烦人的错误。
有没有更简洁的方式来表示所有属性都是必需的,而不明确命名它们?
【问题讨论】:
如果 JSON Schema 规范支持"required": true
就好了,其中布尔值替换了通常的数组。
【参考方案1】:
您可以只使用“minProperties”属性而不是显式命名所有字段。
"type": "object",
"properties":
"elephant": "type": "string",
"giraffe": "type": "string",
"polarBear": "type": "string"
,
"additionalProperties": false,
"minProperties": 3
【讨论】:
迄今为止最好的方法。 谢谢,这很好用。但要记住的一件事是,它取决于"additionalProperties": false
的规范如果 additionalProperties 按规范或默认为 true(如果未指定),则 minProperties 约束可以通过 not 架构对象中的指定之一。
错误信息这样用处不大。您知道自己缺少一处房产,但必须弄清楚是哪一处。尽管如此,还是比每次都复制所有属性要好。
很好的解决方案。我想使用它,尽管我发现它是一个挑战,因为我在给定对象中的#properties 依赖于“oneOff”选择。因此,minProperties 应该理想地在两个整数之间切换,具体取决于用户在另一个属性中的选择。关于是否/如何实现这一点的任何想法?
当您的对象是使用allOf
的另一个对象的扩展时,这不能很好地工作。它要求父对象具有除子对象之外所需的所有属性。如果父对象发生变化,它还需要遍历每个子对象并更新属性计数。【参考方案2】:
我怀疑是否存在指定所需属性的方法,而不是在所需数组中显式命名它们。
但是如果你经常遇到这个问题,我建议你编写一个小脚本,对你的 json-schema 进行后处理,并为所有定义的对象自动添加所需的数组。
脚本只需要遍历json-schema树,并且在每一层,如果找到“properties”关键字,添加一个“required”关键字,所有定义的key都包含在同一层的properties中。
让机器做无聊的事情。
【讨论】:
【参考方案3】:如果您在 python 中使用库 jsonschema,请使用自定义验证器:
首先创建自定义验证器:
# Custom validator for requiring all properties listed in the instance to be in the 'required' list of the instance
def allRequired(validator, allRequired, instance, schema):
if not validator.is_type(instance, "object"):
return
if allRequired and "required" in instance:
# requiring all properties to 'required'
instanceRequired = instance["required"]
instanceProperties = list(instance["properties"].keys())
for property in instanceProperties:
if property not in instanceRequired:
yield ValidationError("%r should be required but only the following are required: %r" % (property, instanceRequired))
for property in instanceRequired:
if property not in instanceProperties:
yield ValidationError("%r should be in properties but only the following are properties: %r" % (property, instanceProperties))
然后扩展一个现有的验证器:
all_validators = dict(Draft4Validator.VALIDATORS)
all_validators['allRequired'] = allRequired
customValidator = jsonschema.validators.extend(
validator=Draft4Validator,
validators=all_validators
)
现在测试:
schema = "allRequired": True
instance = "properties": "name": "type": "string", "required": []
v = customValidator(schema)
errors = validateInstance(v, instance)
你会得到错误:
'name' should be required but only the following are required: []
【讨论】:
好主意。如果我不想在实现中保持语言不可知论,我会选择这个答案。我想这可以推到源头。【参考方案4】:我使用单行代码在代码中执行此操作,例如,如果我想在 DB 中将 required
用于 insert
,但只想在执行 update
时验证架构。
prepareSchema(action)
const actionSchema = R.clone(schema)
switch (action)
case 'insert':
actionSchema.$id = `/$schema.$id-Insert`
actionSchema.required = Object.keys(schema.properties)
return actionSchema
default:
return schema
【讨论】:
【参考方案5】:按照其他人的建议,这是这样的后处理python代码:
def schema_to_strict(schema):
if schema['type'] not in ['object', 'array']:
return schema
if schema['type'] == 'array':
schema['items'] = schema_to_strict(schema['items'])
return schema
for k, v in schema['properties'].items():
schema['properties'][k] = schema_to_strict(v)
schema['required'] = list(schema['properties'].keys())
schema['additionalProperties'] = False
return schema
【讨论】:
以上是关于JSON Schema - 需要所有属性的主要内容,如果未能解决你的问题,请参考以下文章
使用 json-schema 来要求或禁止基于另一个属性值的属性?
JSON Schema 是不是可以使用引用外部属性的 if/then/else