在 JSONSchema 中,如何验证模式至少具有两个属性之一?
In JSONSchema, how do I validate a schema to have at least one of two properties?
现在已经有几个问题要求类似的东西,但我找不到与我想要的完全匹配的问题。
{
"$schema": "http://json-schema.org/draft-07/schema",
"title": "Example schema",
"type": "object",
"properties": {
"youtubeLink": {
"type": "string",
"pattern": "http(?:s?):\/\/(?:www\.)?youtu(?:be\.com\/watch\?v=|\.be\/)([\w\-\_]*)(&(amp;)?[\w\?=]*)?"
},
"assetFile": {
"type": "string"
}
},
"additionalProperties": false,
"dependencies": {
"assetFile": {
"not": {
"required": [
"youtubeLink"
]
}
},
"youtubeLink": {
"not": {
"required": [
"assetFile"
]
}
}
}
}
在示例中您可以看到两个属性,其中一个是必需的,不多也不少。目前您不能同时提供这两个属性,但您可以提供 none。我还希望没有其他属性(已经完成)。我知道这可以通过指定最少量的属性来完成,但如果您有更复杂的架构,这似乎很麻烦。
如果可能的话,我也希望有一个默认的 属性 和默认值,如果给出了两个道具中的 none。
我终于找到了一些可以工作的东西,即使是默认的。但是有没有更短的方法来做到这一点?我是在学习 JSON Schemas 并尝试了几个小时后才得出这个结果的,所以一定有更短的东西。
{
"$schema": "http://json-schema.org/draft-07/schema",
"title": "Config file validation",
"description": "validation schema of the config.json file",
"type": "object",
"properties": {
"youtubeLink": {
"type": "string",
"pattern": "http(?:s?):\/\/(?:www\.)?youtu(?:be\.com\/watch\?v=|\.be\/)([\w\-\_]*)(&(amp;)?[\w\?=]*)?"
},
"assetFile": {
"type": "string",
"pattern": "^(/)?([^/\0\n]+(/)?)+\.(mp3)$"
}
},
"additionalProperties": false,
"if": {
"not": {
"oneOf": [
{
"required": [
"youtubeLink"
]
},
{
"required": [
"assetFile"
]
}
]
}
},
"then": {
"properties": {
"youtubeLink": {
"default": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
}
},
"dependencies": {
"assetFile": {
"not": {
"required": [
"youtubeLink"
]
}
},
"youtubeLink": {
"not": {
"required": [
"assetFile"
]
}
}
}
}
I finally got something to work, even with the default. But is there any shorter way to do this?
是的,您可以使用 oneOf
https://runkit.com/embed/wqbge78zzxb6
const Ajv = require("ajv")
const ajv = new Ajv({allErrors: true})
const schema = {
title: 'Example schema',
oneOf: [
{
type: 'object',
properties: {
youtubeLink: {
type: 'string'
}
},
required: [
'youtubeLink'
],
additionalProperties: false
},
{
type: 'object',
properties: {
assetFile: {
type: 'string'
}
},
required: [
'assetFile'
],
additionalProperties: false
},
{
type: 'object',
properties: {
foo: {
type: 'string',
default: 'hello'
}
},
additionalProperties: false
}
]
}
const validate = ajv.compile(schema)
test({youtubeLink: 'hello'}) // valid
test({assetFile: 'bar'}) // valid
test({assetFile: 'bar', youtubeLink: 'hello'}) // INVALID
test({}) // default value
function test(data) {
const valid = validate(data)
if (valid) console.log("Valid!")
else console.log("Invalid: " + ajv.errorsText(validate.errors))
}
你可以用oneOf
表达的很干净。 oneOf
断言给定模式中只有一个必须有效才能验证模式。
{
"type": "object",
"properties": {
"youtubeLink": {},
"assetFile": {}
},
"additionalProperties": false,
"oneOf": [
{ "required": ["youtubeLink"] },
{ "required": ["assetFile"] }
]
}
- 如果您只有“youtubeLink”,
/oneOf/0
会通过,/oneOf/1
会失败。 (通过)
- 如果您只有“assetFile”,
/oneOf/0
会失败,/oneOf/1
会通过。 (通过)
- 如果两者都有,
/oneOf/0
将通过,/oneOf/1
将通过。 (失败)
- 如果你有none,
/oneOf/0
会失败,/oneOf/1
也会失败。 (失败)
现在已经有几个问题要求类似的东西,但我找不到与我想要的完全匹配的问题。
{
"$schema": "http://json-schema.org/draft-07/schema",
"title": "Example schema",
"type": "object",
"properties": {
"youtubeLink": {
"type": "string",
"pattern": "http(?:s?):\/\/(?:www\.)?youtu(?:be\.com\/watch\?v=|\.be\/)([\w\-\_]*)(&(amp;)?[\w\?=]*)?"
},
"assetFile": {
"type": "string"
}
},
"additionalProperties": false,
"dependencies": {
"assetFile": {
"not": {
"required": [
"youtubeLink"
]
}
},
"youtubeLink": {
"not": {
"required": [
"assetFile"
]
}
}
}
}
在示例中您可以看到两个属性,其中一个是必需的,不多也不少。目前您不能同时提供这两个属性,但您可以提供 none。我还希望没有其他属性(已经完成)。我知道这可以通过指定最少量的属性来完成,但如果您有更复杂的架构,这似乎很麻烦。
如果可能的话,我也希望有一个默认的 属性 和默认值,如果给出了两个道具中的 none。
我终于找到了一些可以工作的东西,即使是默认的。但是有没有更短的方法来做到这一点?我是在学习 JSON Schemas 并尝试了几个小时后才得出这个结果的,所以一定有更短的东西。
{
"$schema": "http://json-schema.org/draft-07/schema",
"title": "Config file validation",
"description": "validation schema of the config.json file",
"type": "object",
"properties": {
"youtubeLink": {
"type": "string",
"pattern": "http(?:s?):\/\/(?:www\.)?youtu(?:be\.com\/watch\?v=|\.be\/)([\w\-\_]*)(&(amp;)?[\w\?=]*)?"
},
"assetFile": {
"type": "string",
"pattern": "^(/)?([^/\0\n]+(/)?)+\.(mp3)$"
}
},
"additionalProperties": false,
"if": {
"not": {
"oneOf": [
{
"required": [
"youtubeLink"
]
},
{
"required": [
"assetFile"
]
}
]
}
},
"then": {
"properties": {
"youtubeLink": {
"default": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
}
},
"dependencies": {
"assetFile": {
"not": {
"required": [
"youtubeLink"
]
}
},
"youtubeLink": {
"not": {
"required": [
"assetFile"
]
}
}
}
}
I finally got something to work, even with the default. But is there any shorter way to do this?
是的,您可以使用 oneOf
https://runkit.com/embed/wqbge78zzxb6
const Ajv = require("ajv")
const ajv = new Ajv({allErrors: true})
const schema = {
title: 'Example schema',
oneOf: [
{
type: 'object',
properties: {
youtubeLink: {
type: 'string'
}
},
required: [
'youtubeLink'
],
additionalProperties: false
},
{
type: 'object',
properties: {
assetFile: {
type: 'string'
}
},
required: [
'assetFile'
],
additionalProperties: false
},
{
type: 'object',
properties: {
foo: {
type: 'string',
default: 'hello'
}
},
additionalProperties: false
}
]
}
const validate = ajv.compile(schema)
test({youtubeLink: 'hello'}) // valid
test({assetFile: 'bar'}) // valid
test({assetFile: 'bar', youtubeLink: 'hello'}) // INVALID
test({}) // default value
function test(data) {
const valid = validate(data)
if (valid) console.log("Valid!")
else console.log("Invalid: " + ajv.errorsText(validate.errors))
}
你可以用oneOf
表达的很干净。 oneOf
断言给定模式中只有一个必须有效才能验证模式。
{
"type": "object",
"properties": {
"youtubeLink": {},
"assetFile": {}
},
"additionalProperties": false,
"oneOf": [
{ "required": ["youtubeLink"] },
{ "required": ["assetFile"] }
]
}
- 如果您只有“youtubeLink”,
/oneOf/0
会通过,/oneOf/1
会失败。 (通过) - 如果您只有“assetFile”,
/oneOf/0
会失败,/oneOf/1
会通过。 (通过) - 如果两者都有,
/oneOf/0
将通过,/oneOf/1
将通过。 (失败) - 如果你有none,
/oneOf/0
会失败,/oneOf/1
也会失败。 (失败)