在 json 模式中验证 2 种可能的数据类型
Posted
技术标签:
【中文标题】在 json 模式中验证 2 种可能的数据类型【英文标题】:validate 2 possible types of data in jsonchema 【发布时间】:2019-04-11 04:09:42 【问题描述】:我花了一整天的时间试图让它发挥作用,将发布一个参考列表和我在提问后尝试过的事情。
这是我的 jsonschema:
"data": [
"required": "effort",
"decisive": "maybe",
"field1": 7
,
"required": "effort",
"decisive": "no",
"field1": 6
],
"schema":
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "array",
"items":
"type": "object",
"properties":
"field1":
"type": "string",
"pattern": "[A-Z]",
"title": "field1"
,
"required":
"type": "string",
"title": "required",
"readonly": true
,
"decisive":
"type": "string",
"title": "Decisive",
"enum": ["yes", "no", "maybe", "not now"]
考虑 jsonschema 的确切部分,但带有 field1
元素,如下所示:
"field1":
"type": "integer",
"minimum": 5,
"maximum": 10,
"title": "field1"
第一个示例仅验证其字段中的大写字母1
第二个想要一个介于 5 和 10 之间的整数。
你如何让它验证其中任何一个,所以两者都被接受 -
或者只有大写字母 或 5 到 10 之间的整数?哦 - 上面数据部分中的 field1 并不重要,它是所需的默认值。
我尝试过各种想法—— with oneOf - here, here, here
参数 - here
其他属性 - here
必填 - here
直观的做法是使用 oneOf on 模式,但正如许多问题中提到的那样,oneOf 在属性部分内不做任何事情,只是在它之外做任何事情。因此,我尝试在 oneOf 中拥有完全相同的属性,但只有一个区别,如上所述。这也不起作用,并且包含很多必须以某种方式避免的重复。
有谁知道如何解决这个问题?我没主意了..
【问题讨论】:
出于兴趣,这是某种任务还是工作?过去几天看到几个非常相似的问题? 它的工作。我认为每个人都在尝试将 jsonschema 用于表单,即使它不是为此而设计的。我现在有一个question with a bounty 试图将我们从羊驼中拯救出来,这样我们就可以更多地留在 Python 中。 【参考方案1】:你是 oneOf
的正确方向之一,但你真正想要的是 anyOf
。几乎每次你认为你想要oneOf
,你真的想要anyOf
。请记住,properties
的值与其他任何模式一样都是模式。您可以像在其他任何地方一样使用布尔关键字。
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "array",
"items":
"type": "object",
"properties":
"field1":
"title": "field1"
"anyOf": [
"type": "string",
"pattern": "[A-Z]"
,
"type": "integer",
"minimum": 5,
"maximum": 10
]
,
"required":
"type": "string",
"title": "required",
"readonly": true
,
"decisive":
"type": "string",
"title": "Decisive",
"enum": ["yes", "no", "maybe", "not now"]
编辑 1
当你听说oneOf
不能在属性内部使用时,他们正在谈论的就是这种事情。
"type": "object",
"properties":
"anyOf": [
"field1": ...
,
"field1": ...
],
"required": ... ,
"decisive": ...
编辑 2
因为它出现在 cmets 中,所以这里更好地解释了为什么 oneOf
几乎从来都不是正确的选择。需要明确的是,oneOf
将始终代替 anyOf
。如果anyOf
不存在,JSON Schema 不会失去任何表达能力。
但是,anyOf
是一个更精确的工具。当anyOf
可以使用oneOf
时,就像在工具箱中有一个简单的羊角锤时使用大锤敲钉子一样。
anyOf
是布尔或运算。 oneOf
是布尔“异或”(XOR) 操作。 “XOR”几乎没有用处,现代语言甚至不支持它。 OR 通常用运算符||
表示。 XOR 没有类比。
anyOf
表示任何项都可以为真。 oneOf
表示只有一个项可以为真。当您使用oneOf
时,验证器需要测试所有 模式,以确保一个模式验证为真,其余的验证为假。当您使用anyOf
时,验证器可以在找到验证为真的模式后立即停止。这称为“短路”,所有现代编程语言在评估 OR 操作时都会这样做。当模式是互斥的(它们几乎总是如此)时,在找到一个模式后继续验证模式纯粹是浪费,因此应该避免。
我认为oneOf
被过度使用了,因为从自然语言的角度来看,它听起来是对的。
【讨论】:
虽然这个模式可以工作,但我不确定你为什么认为oneOf
不是正确的解决方案。 @cardamom 如果您使用此模式但将anyOf
替换为oneOf
,会发生什么情况?它的行为仍然符合您的预期吗?在这种情况下,它应该可以,但 anyOf
和 oneOf
在其他情况下的行为会有所不同。
@JasonDesrosiers 感谢您的回答。 @Relequestual 我仍然在努力让一切都在羊驼表单验证中工作,但如果你们都认为这应该工作,问题可能是别的。问another 羊驼问题。我不明白的是,anyOf
是 inside 属性,所有内容都告诉我们不要这样做,例如 this 和 this。充满矛盾……
伙计们,谢谢,它有效!如果我使用 Python 库 fastjsonschema 运行它,它会进行完全正确的验证。羊驼身上有某种虫子。需要知道该怪谁..
@cardamom 那些关于anyOf
insdie 属性的链接...您所看到的是,properties
对象的任何键都与 JSON 实例中的键相关。 properties
对象中每个键的值是一个 JSON 模式。因此,您上面的内容是可以的。有意义吗?
文档中没有任何内容表明 alpaca.js 支持来自 JSON Schema 的 anyOf
或任何 *Of
关键字。 JSON Schema 不是为创建表单而设计的,因此生成表单的库倾向于按照他们认为合适的方式做自己的事情。有github问题。以上是关于在 json 模式中验证 2 种可能的数据类型的主要内容,如果未能解决你的问题,请参考以下文章