JSON 条件数组对象的模式验证
JSON schema validation of conditional array objects
我有两种类型的数据集,csv 或固定长度数据。在 csv 数据中,字段列表只是一个名称列表,
而在固定长度数据中,每个字段由 fieldName 和 fieldLength 指定。
我需要一个 json 模式来验证这两种情况,但在尝试了几种解决方案之后,包括
,我不确定是否可以完成。或许我对 JSON 模式的理解还远非完美。
json :
{
"dataset": "csv data",
"dataFormat": "csv",
"fieldList": [{
"fieldName": "id"
},
{
"fieldName": "num"
},
{
"fieldName": "struct"
}
]
}
{
"dataset": "fixed length",
"dataFormat": "fixed",
"fieldList": [{
"fieldName": "id",
"fieldLength": 13
},
{
"fieldName": "num"
},
{
"fieldName": "struct"
}
]
}
JSON 架构:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"dataset",
"dataFormat",
"fieldList"
],
"properties": {
"dataset": {
"$id": "#/properties/dataset",
"type": "string"
},
"dataFormat": {
"$id": "#/properties/dataFormat",
"type": "string",
"enum": [
"csv",
"fixed"
]
},
"fieldList": {
"$id": "#/properties/fieldList",
"type": "array",
"additionalItems": true,
"items": {
"$id": "#/properties/fieldList/items",
"type": "object",
"additionalProperties": true,
"required": [
"fieldName"
],
"if": {
"properties": {
"dataFormat": {
"const": "fixed"
}
}
},
"then": {"items":{
"required": [
"fieldLength"
]}
},
"properties": {
"fieldName": {
"$id": "#/properties/fieldList/items/properties/fieldName",
"type": "string"
},
"fieldLength": {
"$id": "#/properties/fieldList/items/properties/fieldLength",
"type": "integer"
}
}
}
}
}
}
两个文档都得到了肯定的验证,即使在 "fixed" 类型中只有第一项包含所需的 fieldLength。
有什么建议吗?
您的架构中有一些可以改进的地方:
if
/then
放错地方了。现在,if
在 "fieldList"
items
中寻找 "dataFormat"
属性,但从未找到。 then
同样试图在 "fieldList".items.items
中强制存在 "fieldLength"
属性(因为 "fieldList".items
是 object
而不是 array
,那将被忽略。
- 您应该删除
additionalItems
属性。引用 json-schema.org:
When items
is a single schema, the additionalItems
keyword is meaningless, and it should not be used.
- 您可以删除
additionalProperties
属性,因为它的默认值已经是 true
。 json-schema.org 的另一段引述:
The additionalProperties
keyword is used to control the handling of extra stuff, that is, properties
whose names are not listed in the properties keyword. By default any additional properties are allowed.
$id
属性并没有增加多少价值(并且与较新的 2019-09 草案不兼容,它们只允许出现在新的 $anchor
关键字中)。你可能想忽略那些。
您的主要问题是此处的第 1 点。
你应该能够通过在顶层添加这样的东西来实现你想要的:
"oneOf": [
{
"properties": {
"dataFormat": { "const": "csv" }
}
},
{
"properties": {
"dataFormat": { "const": "fixed" },
"fieldList": {
"items": {
"required": ["fieldLength"]
}
}
}
}
]
完整的架构可能如下所示:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"dataset",
"dataFormat",
"fieldList"
],
"properties": {
"dataset": {
"$id": "#/properties/dataset",
"type": "string"
},
"dataFormat": {
"$id": "#/properties/dataFormat",
"type": "string",
"enum": [
"csv",
"fixed"
]
},
"fieldList": {
"$id": "#/properties/fieldList",
"type": "array",
"items": {
"$id": "#/properties/fieldList/items",
"type": "object",
"required": [
"fieldName"
],
"properties": {
"fieldName": {
"$id": "#/properties/fieldList/items/properties/fieldName",
"type": "string"
},
"fieldLength": {
"$id": "#/properties/fieldList/items/properties/fieldLength",
"type": "integer"
}
}
}
}
},
"oneOf": [
{
"properties": {
"dataFormat": {
"const": "csv"
}
}
},
{
"properties": {
"dataFormat": {
"const": "fixed"
},
"fieldList": {
"items": {
"required": [
"fieldLength"
]
}
}
}
}
]
}
为了完整起见:您也可以使用 if
/then
实现相同的效果:
"if": {
"properties": {
"dataFormat": {
"const": "fixed"
}
}
},
"then": {
"properties": {
"fieldList": {
"items": {
"required": [
"fieldLength"
]
}
}
}
}
我有两种类型的数据集,csv 或固定长度数据。在 csv 数据中,字段列表只是一个名称列表,
而在固定长度数据中,每个字段由 fieldName 和 fieldLength 指定。
我需要一个 json 模式来验证这两种情况,但在尝试了几种解决方案之后,包括
json :
{
"dataset": "csv data",
"dataFormat": "csv",
"fieldList": [{
"fieldName": "id"
},
{
"fieldName": "num"
},
{
"fieldName": "struct"
}
]
}
{
"dataset": "fixed length",
"dataFormat": "fixed",
"fieldList": [{
"fieldName": "id",
"fieldLength": 13
},
{
"fieldName": "num"
},
{
"fieldName": "struct"
}
]
}
JSON 架构:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"dataset",
"dataFormat",
"fieldList"
],
"properties": {
"dataset": {
"$id": "#/properties/dataset",
"type": "string"
},
"dataFormat": {
"$id": "#/properties/dataFormat",
"type": "string",
"enum": [
"csv",
"fixed"
]
},
"fieldList": {
"$id": "#/properties/fieldList",
"type": "array",
"additionalItems": true,
"items": {
"$id": "#/properties/fieldList/items",
"type": "object",
"additionalProperties": true,
"required": [
"fieldName"
],
"if": {
"properties": {
"dataFormat": {
"const": "fixed"
}
}
},
"then": {"items":{
"required": [
"fieldLength"
]}
},
"properties": {
"fieldName": {
"$id": "#/properties/fieldList/items/properties/fieldName",
"type": "string"
},
"fieldLength": {
"$id": "#/properties/fieldList/items/properties/fieldLength",
"type": "integer"
}
}
}
}
}
}
两个文档都得到了肯定的验证,即使在 "fixed" 类型中只有第一项包含所需的 fieldLength。 有什么建议吗?
您的架构中有一些可以改进的地方:
if
/then
放错地方了。现在,if
在"fieldList"
items
中寻找"dataFormat"
属性,但从未找到。then
同样试图在"fieldList".items.items
中强制存在"fieldLength"
属性(因为"fieldList".items
是object
而不是array
,那将被忽略。- 您应该删除
additionalItems
属性。引用 json-schema.org:When
items
is a single schema, theadditionalItems
keyword is meaningless, and it should not be used. - 您可以删除
additionalProperties
属性,因为它的默认值已经是true
。 json-schema.org 的另一段引述:The
additionalProperties
keyword is used to control the handling of extra stuff, that is,properties
whose names are not listed in the properties keyword. By default any additional properties are allowed. $id
属性并没有增加多少价值(并且与较新的 2019-09 草案不兼容,它们只允许出现在新的$anchor
关键字中)。你可能想忽略那些。
您的主要问题是此处的第 1 点。 你应该能够通过在顶层添加这样的东西来实现你想要的:
"oneOf": [
{
"properties": {
"dataFormat": { "const": "csv" }
}
},
{
"properties": {
"dataFormat": { "const": "fixed" },
"fieldList": {
"items": {
"required": ["fieldLength"]
}
}
}
}
]
完整的架构可能如下所示:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"dataset",
"dataFormat",
"fieldList"
],
"properties": {
"dataset": {
"$id": "#/properties/dataset",
"type": "string"
},
"dataFormat": {
"$id": "#/properties/dataFormat",
"type": "string",
"enum": [
"csv",
"fixed"
]
},
"fieldList": {
"$id": "#/properties/fieldList",
"type": "array",
"items": {
"$id": "#/properties/fieldList/items",
"type": "object",
"required": [
"fieldName"
],
"properties": {
"fieldName": {
"$id": "#/properties/fieldList/items/properties/fieldName",
"type": "string"
},
"fieldLength": {
"$id": "#/properties/fieldList/items/properties/fieldLength",
"type": "integer"
}
}
}
}
},
"oneOf": [
{
"properties": {
"dataFormat": {
"const": "csv"
}
}
},
{
"properties": {
"dataFormat": {
"const": "fixed"
},
"fieldList": {
"items": {
"required": [
"fieldLength"
]
}
}
}
}
]
}
为了完整起见:您也可以使用 if
/then
实现相同的效果:
"if": {
"properties": {
"dataFormat": {
"const": "fixed"
}
}
},
"then": {
"properties": {
"fieldList": {
"items": {
"required": [
"fieldLength"
]
}
}
}
}