有没有办法在嵌套的 JSON 模式中实现等效于 CHECK 约束的 Postgres?假设我们有具有两个属性的数据,每个属性都有嵌套的属性。JSON Schema 如何使第一个对象的所需内容依赖于第二个对象?
我的真实案例场景是为 GeoJSON 对象构建一个 JSON 模式,该模式具有几何对象(即 Point 或 Polygon,或 null),以及“属性”对象中的其他属性。我想根据几何类型更改所需的属性。
我失败了以下两种解决方案:
这将验证,因为属性/位置覆盖缺少几何体:
{
"attributes": {
"name": "Person2",
"place": "City2"
},
"geometry": null
}
这也将验证,因为几何不再需要属性/位置:
{
"attributes": {
"name": "Person1"
},
"geometry": {
"type": "Point",
"coordinates": []
}
}
编辑
基于 Relequestual 的回答,这是我得到的令人不满意的结果:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"geometryIsPoint": {
"type": "object",
"required": ["type"],
"properties": {
"type": {
"const": "Point"
}
}
},
"partialAttributes": {
"type": "object",
"required": ["name"],
"properties": {
"name": {
"type": "string"
},
"place": {
"type": "string"
}
}
},
"fullAttributes": {
"type": "object",
"required": ["name", "place"],
"properties": {
"name": {
"type": "string"
},
"place": {
"type": "string"
}
}
},
"conditionalAttributes": {
"allOf": [
{
"if": {
"$ref": "#/definitions/geometryIsPoint"
},
"then": {
"$ref": "#/definitions/partialAttributes"
},
"else": {
"$ref": "#/definitions/fullAttributes"
}
}
]
}
},
"properties": {
"attributes": {
"$ref": "#/definitions/conditionalAttributes"
},
"geometry": {
"$ref": "#/definitions/geometryIsPoint"
}
}
}
如果attributes/place
删除该属性,则此架构将不会验证以下内容。
{
"attributes": {
"name": "Person",
"place": "INVALID IF THIS LINE IS REMOVED ;-("
},
"geometry": {
"type": "Point",
"coordinates": {}
}
}
您可以使用if/then/else
关键字有条件地应用子模式。
我们只想要if
和then
为您解决。
两者的值都必须是 JSON Schema。
如果 的值if
导致肯定的断言(当架构应用于实例并且验证成功时),则架构值then
应用于实例。
这是架构。
我已在https://jsonschema.dev 上预加载了架构和数据,以便您可以对其进行实时测试。
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"geometryIsPoint": {
"required": [
"type"
],
"properties": {
"type": {
"const": "Point"
}
}
},
"geometryAsPoint": {
"required": [
"coordinates"
],
"properties": {
"coordinates": {
"type": "array"
}
}
},
"geometry": {
"allOf": [
{
"if": {
"$ref": "#/definitions/geometryIsPoint"
},
"then": {
"$ref": "#/definitions/geometryAsPoint"
}
}
]
}
},
"properties": {
"geometry": {
"$ref": "#/definitions/geometry"
}
}
}
该属性geometry
引用了定义geometry
。
allOf
是一个模式数组。
allOf[0].if
引用模式定义为的值geometryIsPoint
。
定义为的架构geometryIsPoint
应用于该geometry
值。如果它成功验证,则then
应用引用的模式。
你不必使用引用来做任何这些,但我觉得它使意图更清晰。
根据需要扩展架构,allOf
为您想要识别的任意数量的几何类型添加架构。
编辑:
您遇到了else
条件的条件,因为if
验证失败。让我解释。
这是一个更新的架构,用于涵盖您修改后的用例。
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"geometry": {
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"enum": [
"Point",
"somethingelse",
null
]
}
}
},
"geometryIsPoint": {
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"const": "Point"
}
}
},
"attributes": {
"properties": {
"name": {
"type": "string"
},
"place": {
"type": "string"
}
}
},
"partialAttributes": {
"type": "object",
"required": [
"name"
]
},
"fullAttributes": {
"type": "object",
"required": [
"name",
"place"
]
},
"conditionalAttributes": {
"allOf": [
{
"if": {
"required": [
"geometry"
],
"properties": {
"geometry": {
"$ref": "#/definitions/geometryIsPoint"
}
}
},
"then": {
"required": [
"attributes"
],
"properties": {
"attributes": {
"$ref": "#/definitions/partialAttributes"
}
}
},
"else": {
"required": [
"attributes"
],
"properties": {
"attributes": {
"$ref": "#/definitions/fullAttributes"
}
}
}
}
]
}
},
"properties": {
"attributes": {
"$ref": "#/definitions/attributes"
},
"geometry": {
"$ref": "#/definitions/geometry"
}
},
"allOf": [
{
"$ref": "#/definitions/conditionalAttributes"
}
]
}
这是一个JSON Schema 开发链接,您可以对其进行测试。
我们在这里所做的是分散关注。
所述的“形状”attributes
和geometry
在与相应的键定义所定义。这些模式不会断言这些对象中需要哪些键,只断言如果提供它们必须是什么。
因为$ref
在模式中忽略了模式中的所有其他关键字(对于草案 7 或以下),在根级别,我conditionalAttributes
将allOf
.
conditionalAttributes
是一个定义的 JSON 模式。我已经使用过,allOf
因此您可以添加更多条件检查。
的值conditionalAttributes.allOf[0].if
是一个 JSON 模式,并应用于 JSON 实例的根。它需要一个键,geometry
并且值为geometryIsPoint
。(如果省略required
,您最终会遇到验证问题,因为省略该键将通过 if 条件)。
当实例产生true
对if
值模式的断言(验证有效)时,then
值模式将在根级别应用。
因为它在根级别应用并且您想要检查嵌套属性的值,所以您必须properties
像在架构的根级别一样使用它。这就是您if/then/else
在实例的不同深度上执行条件模式应用程序 ( ) 的方式。
您可以通过将架构值之一更改为false
并查看错误来测试条件解析。请记住,true
并且false
是有效的 JSON 模式,因此"then": false
如果您希望then
应用模式(如if
模式断言验证正常),您可以写入导致错误。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句