问题
What I'm trying to accomplish in json-schema: when the property enabled
is true
, certain other properties should be required. When false
, those properties should be disallowed.
Here's my json-schema:
{
"type": "object",
"properties": {
"enabled": { "type": "boolean" }
},
"required" : ["enabled"],
"additionalProperties" : false,
"if": {
"properties": {
"enabled": true
}
},
"then": {
"properties": {
"description" : { "type" : "string" },
"count": { "type": "number" }
},
"required" : ["description", "count"]
}
}
Validating using ajv
version 6.5, this had the result of requiring count
, etc. regardless of the value of enabled
. For instance, for data:
{ "enabled": false }
My validation errors are:
[ { keyword: 'required',
dataPath: '',
schemaPath: '#/then/required',
params: { missingProperty: 'description' },
message: 'should have required property \'description\'' },
{ keyword: 'required',
dataPath: '',
schemaPath: '#/then/required',
params: { missingProperty: 'count' },
message: 'should have required property \'count\'' },
{ keyword: 'if',
dataPath: '',
schemaPath: '#/if',
params: { failingKeyword: 'then' },
message: 'should match "then" schema' } ]
How can I accomplish this using json-schema draft-7
?
Note that this question is similar to, but has more stringent requirements than:
jsonSchema attribute conditionally required.
回答1:
Try this schema:
{
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
}
},
"required": [
"enabled"
],
"if": {
"properties": {
"enabled": {
"const": true
}
}
},
"then": {
"properties": {
"enabled": {
"type": "boolean"
},
"description": {
"type": "string"
},
"count": {
"type": "number"
},
"additionalProperties": false
},
"required": [
"description",
"count"
]
},
"else": {
"properties": {
"enabled": {
"type": "boolean"
}
},
"additionalProperties": false
}
}
If you need "additionalProperties": false
you have to enumerate all properties in both then
and else
. If you can accept additional properties the schema could be simplier:
{
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
}
},
"required": [
"enabled"
],
"if": {
"properties": {
"enabled": {
"const": true
}
}
},
"then": {
"properties": {
"description": {
"type": "string"
},
"count": {
"type": "number"
}
},
"required": [
"description",
"count"
]
}
}
I checked with ajv cli.
Valid: {"enabled": false}
Invalid: {"enabled": true}
Valid: {"enabled": true, "description":"hi", "count":1}
回答2:
This was inspired by vearutop's excellent answer. I think it might be a little shorter, and accomplishes my stated purpose.
{
"type": "object",
"oneOf" : [
{
"properties": {
"enabled": { "const": false }
},
"required": ["enabled"],
"additionalProperties": false
},
{
"properties": {
"enabled": { "const": true },
"description": { "type": "string" },
"count": { "type": "number" }
},
"required": [ "enabled", "description", "count"],
"additionalProperties": false
}
]
}
As pointed out in the comments, this is a specific variant of the Enum strategy spelled out in this answer.
回答3:
To achieve that, in the if
statement you need to use the const
keyword, so the schema will look like:
{
"type": "object",
"properties": {
"enabled": { "type": "boolean" }
},
"required" : ["enabled"],
"additionalProperties" : false,
"if": {
"properties": {
"enabled": {"const": true}
}
},
"then": {
"properties": {
"description" : { "type" : "string" },
"count": { "type": "number" }
},
"required" : ["description", "count"]
}
}
来源:https://stackoverflow.com/questions/50340967/use-json-schema-to-require-or-disallow-properties-based-on-another-property-valu