如何指定 属性 不应该存在或包含 null?
How to specify if a property should not exist or contain null?
一年前我曾问过 ,我得到了很好的答案,从那以后我就一直在使用该架构。
现在源数据已更改 - 架构在以下情况下失败:
源数据包含许多属性,但其中只有两个与此问题相关:"key" 和 "value" - "value" 的类型取决于 "key"-
例如:
如果key是"comment",value的类型是{"Text":"commentValue"}
.
如果key是"offset",那么value的类型就是{"seconds":int}
.
如果key是"weather",那么value的类型就是{"value": Enum["sun", "clouds", "rain"...]}
一些键没有值 属性,因此模式应该禁止它与这些键一起出现 - 例如,如果键是 "standby",则值 属性 根本不应该出现——这就是我当前的架构做得很好的地方。
但是,现在数据源已经改变,我得到 "value" :{}
作为我的 Json 的一部分,它曾经被省略 - 而当前的模式不允许它。
所以我的问题是 - 如何允许这两个选项之一?我尝试了我能想到的 anyOf
的任意组合,但惨败 - Newtonsoft.Json.Schema.JSchema
无法解析文本。
这是我当前使用的架构的简化版本:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "TestOptionalObject",
"type": "object",
"additionalProperties": false,
"required": [
"test"
],
"properties": {
"test": {
"$ref": "#/definitions/test"
}
},
"definitions": {
"test": {
"type": "object",
"required": [
"key"
],
"properties": {
"key": {
"type": "string",
"enum": [
"comment",
"offset",
"standby",
"status_unsure",
"status_ok"
]
}
},
"allOf": [
{
"if": {
"properties": {
"event": {
"enum": [
"standby",
"status_unsure",
"status_ok"
]
}
}
},
"then": {
"properties": {
"value": false
}
}
},
{
"if": {
"properties": {
"key": {
"const": "comment"
}
}
},
"then": {
"properties": {
"value": {
"$ref": "#/definitions/commentValue"
}
}
}
},
{
"if": {
"properties": {
"key": {
"const": "offset"
}
}
},
"then": {
"properties": {
"value": {
"$ref": "#/definitions/offsetValue"
}
}
}
}
]
},
"commentValue": {
"type": "object",
"additionalProperties": false,
"required": [
"text"
],
"properties": {
"text": {
"type": "string"
}
}
},
"offsetValue": {
"type": "object",
"additionalProperties": false,
"required": [
"seconds"
],
"properties": {
"seconds": {
"type": "integer",
"format": "int32"
}
}
}
}
}
以下是我尝试过的一些方法:
"then": {
"properties": {
"anyOf": [
{ "value": false },
{ "value": null }
]
}
}
"then": {
"anyOf": [
{
"properties": {
{ "value": false }
},
"properties": {
{ "value": null }
}
]
}
"then": {
"properties": {
"value":
"anyOf": [false, null ]
}
}
Json 个验证示例:
应该失败:
{
"test": {
"key": "comment",
"value": {"seconds":12}
}
}
{
"test": {
"key": "standby",
"value": {"asdf":12}
}
}
应该通过:
{
"test": {
"key": "comment",
"value": {"text":"comment text"}
}
}
{
"test": {
"key": "offset",
"value": {"seconds":12}
}
}
{
"test": {
"key": "standby"
}
}
{
"test": {
"key": "standby",
"value": {}
}
}
请注意最后一个示例 - value
属性 是一个空对象 - 它也应该通过但在当前架构中失败,因为 value
属性 不应该对于这个键根本不存在。
你很接近,但不完全是。您必须记住 allOf
是一个子模式数组(JSON 模式)。 (Null 不是有效的架构,因此您可能遇到了一些 "not a valid schema" 错误。)
因此,考虑来自 allOf[0]
...
的修改后的子模式
{
"if": {
"properties": {
"key": {
"enum": [
"standby",
"status_unsure",
"status_ok"
]
}
}
},
"then": {
"properties": {
"value": {
"type": [
"object"
],
"additionalProperties": false
}
}
}
}
你可以在这里测试:https://jsonschema.dev/s/EfNI1
if
块保持不变。 (虽然我已经更正了我认为在您从真实模式简化中使用 event
而不是 key
的错误。)
then
块需要定义对象(已被definitions.test
检查)有一个键value
,其中value
的值是一个对象,并且没有属性(又名空对象)。
要达到 "an empty object",您需要使用 additionalProperties
。
additionalProperties
将其值子模式应用于 properties
中未定义的所有属性或与 patternProperties
.[=47= 中的键(正则表达式)匹配的所有属性]
false
作为模式总是无法通过验证。
没有 properites
的 additionalProperties
适用于所有属性,因此值为 false,验证 "is an empty object".
一年前我曾问过
现在源数据已更改 - 架构在以下情况下失败:
源数据包含许多属性,但其中只有两个与此问题相关:"key" 和 "value" - "value" 的类型取决于 "key"-
例如:
如果key是"comment",value的类型是{"Text":"commentValue"}
.
如果key是"offset",那么value的类型就是{"seconds":int}
.
如果key是"weather",那么value的类型就是{"value": Enum["sun", "clouds", "rain"...]}
一些键没有值 属性,因此模式应该禁止它与这些键一起出现 - 例如,如果键是 "standby",则值 属性 根本不应该出现——这就是我当前的架构做得很好的地方。
但是,现在数据源已经改变,我得到 "value" :{}
作为我的 Json 的一部分,它曾经被省略 - 而当前的模式不允许它。
所以我的问题是 - 如何允许这两个选项之一?我尝试了我能想到的 anyOf
的任意组合,但惨败 - Newtonsoft.Json.Schema.JSchema
无法解析文本。
这是我当前使用的架构的简化版本:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "TestOptionalObject",
"type": "object",
"additionalProperties": false,
"required": [
"test"
],
"properties": {
"test": {
"$ref": "#/definitions/test"
}
},
"definitions": {
"test": {
"type": "object",
"required": [
"key"
],
"properties": {
"key": {
"type": "string",
"enum": [
"comment",
"offset",
"standby",
"status_unsure",
"status_ok"
]
}
},
"allOf": [
{
"if": {
"properties": {
"event": {
"enum": [
"standby",
"status_unsure",
"status_ok"
]
}
}
},
"then": {
"properties": {
"value": false
}
}
},
{
"if": {
"properties": {
"key": {
"const": "comment"
}
}
},
"then": {
"properties": {
"value": {
"$ref": "#/definitions/commentValue"
}
}
}
},
{
"if": {
"properties": {
"key": {
"const": "offset"
}
}
},
"then": {
"properties": {
"value": {
"$ref": "#/definitions/offsetValue"
}
}
}
}
]
},
"commentValue": {
"type": "object",
"additionalProperties": false,
"required": [
"text"
],
"properties": {
"text": {
"type": "string"
}
}
},
"offsetValue": {
"type": "object",
"additionalProperties": false,
"required": [
"seconds"
],
"properties": {
"seconds": {
"type": "integer",
"format": "int32"
}
}
}
}
}
以下是我尝试过的一些方法:
"then": {
"properties": {
"anyOf": [
{ "value": false },
{ "value": null }
]
}
}
"then": {
"anyOf": [
{
"properties": {
{ "value": false }
},
"properties": {
{ "value": null }
}
]
}
"then": {
"properties": {
"value":
"anyOf": [false, null ]
}
}
Json 个验证示例:
应该失败:
{
"test": {
"key": "comment",
"value": {"seconds":12}
}
}
{
"test": {
"key": "standby",
"value": {"asdf":12}
}
}
应该通过:
{
"test": {
"key": "comment",
"value": {"text":"comment text"}
}
}
{
"test": {
"key": "offset",
"value": {"seconds":12}
}
}
{
"test": {
"key": "standby"
}
}
{
"test": {
"key": "standby",
"value": {}
}
}
请注意最后一个示例 - value
属性 是一个空对象 - 它也应该通过但在当前架构中失败,因为 value
属性 不应该对于这个键根本不存在。
你很接近,但不完全是。您必须记住 allOf
是一个子模式数组(JSON 模式)。 (Null 不是有效的架构,因此您可能遇到了一些 "not a valid schema" 错误。)
因此,考虑来自 allOf[0]
...
{
"if": {
"properties": {
"key": {
"enum": [
"standby",
"status_unsure",
"status_ok"
]
}
}
},
"then": {
"properties": {
"value": {
"type": [
"object"
],
"additionalProperties": false
}
}
}
}
你可以在这里测试:https://jsonschema.dev/s/EfNI1
if
块保持不变。 (虽然我已经更正了我认为在您从真实模式简化中使用 event
而不是 key
的错误。)
then
块需要定义对象(已被definitions.test
检查)有一个键value
,其中value
的值是一个对象,并且没有属性(又名空对象)。
要达到 "an empty object",您需要使用 additionalProperties
。
additionalProperties
将其值子模式应用于properties
中未定义的所有属性或与patternProperties
.[=47= 中的键(正则表达式)匹配的所有属性]false
作为模式总是无法通过验证。
properites
的 additionalProperties
适用于所有属性,因此值为 false,验证 "is an empty object".