有没有办法让JSON架构属性成为数字或null
?
我正在构建一个包含heading
属性的API。可以是介于0(含)和360(独占)之间的数字,也可以为null,因此以下输入均可:
{"heading": 5}
{"heading": 0}
{"heading": null}
{"heading": 12}
{"heading": 120}
{"heading": null}
以下输入是错误的:
{"heading": 360}
{"heading": 360.1}
{"heading": -5}
{"heading": false}
{"heading": "X"}
{"heading": 1200}
{"heading": false}
附录:
anyOf
显然是正确的答案。为清晰起见,添加完整的架构。
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"additionalProperties": false,
"properties": {
"heading": {
"anyOf": [
{"type": "number"},
{"type": "null"}
]
}
}
}
答案 0 :(得分:26)
在draft-04中,您将使用anyOf指令:
{
"anyOf": [
{
"type": "number",
"minimum": 0,
"maximum": 360,
"exclusiveMaximum": true
},
{
"type": "null"
}
]
}
您也可以使用“type”:[“number”,“null”],如Adam建议的那样,但我认为anyOf更干净(只要你使用draft-04实现),并将最小和最大声明联系起来明确地说明这个数字。
免责声明:我对python实现一无所知,我的答案是关于json架构的。
答案 1 :(得分:25)
诀窍是使用类型数组。而不是:
"type": "number"
使用:
"type": ["number", "null"]
如果值为数字,则以下代码强制执行数字或空值策略以及数字限制:
from jsonschema import validate
from jsonschema.exceptions import ValidationError
import json
schema=json.loads("""{
"$schema": "http://json-schema.org/schema#",
"description": "Schemas for heading: either a number within [0, 360) or null.",
"title": "Tester for number-or-null schema",
"properties": {
"heading": {
"type": ["number", "null"],
"exclusiveMinimum": false,
"exclusiveMaximum": true,
"minimum": 0,
"maximum": 360
}
}
}""")
inputs = [
{"heading":5}, {"heading":0}, {"heading":360}, {"heading":360.1},
{"heading":-5},{"heading":None},{"heading":False},{"heading":"X"},
json.loads('''{"heading":12}'''),json.loads('''{"heading":120}'''),
json.loads('''{"heading":1200}'''),json.loads('''{"heading":false}'''),
json.loads('''{"heading":null}''')
]
for input in inputs:
print "%-30s" % json.dumps(input),
try:
validate(input, schema)
print "OK"
except ValidationError as e:
print e.message
给出了:
{"heading": 5} OK
{"heading": 0} OK
{"heading": 360} 360.0 is greater than or equal to the maximum of 360
{"heading": 360.1} 360.1 is greater than or equal to the maximum of 360
{"heading": -5} -5.0 is less than the minimum of 0
{"heading": null} OK
{"heading": false} False is not of type u'number', u'null'
{"heading": "X"} 'X' is not of type u'number', u'null'
{"heading": 12} OK
{"heading": 120} OK
{"heading": 1200} 1200.0 is greater than or equal to the maximum of 360
{"heading": false} False is not of type u'number', u'null'
{"heading": null} OK
答案 2 :(得分:0)
此答案与JSON模式无关,但是如果您将来希望考虑一些替代方法,那么它将很有用。
如果仅希望多个元素中的一个可验证元素成功,则可以直接编写以下内容:
Validatable<?> validatableElement =
new OneOf(
"global",
new ErrorStub("This field should be either integer, or null, or absent at all"),
new AsInteger(
new Required(
new IndexedValue("header", json)
)
),
new IsAbsent<>(
new IndexedValue("header", json)
)
);
如果有一个值并且它是整数,那么结果将是以下内容:
Result<?> result = validatableElement.result();
assertTrue(result.isSuccessful());
assertEquals(
24,
result.value().raw()
);
如果没有传递标题或它为null,那么结果将如下所示:
assertTrue(result.isSuccessful());
assertFalse(result.value().isPresent());
有关此方法和实现该方法的库的更多信息,请查看quick start entry并提供更多示例。