Reputation: 981
I'm trying to set a value for maxItems based on another value in JSON-data. Label is 'yyyy_mm' and maxItems should be the number of days in month 'mm' in year 'yyyy' (leap year or not). This is what I have so far.
The schema:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"period": {
"type": "object",
"properties": {
"label": {
"type": "string",
"pattern": "^\\d{4}_(0[1-9]|1[0-2])$"
}
},
"required": [
"label"
]
},
"days": {
"type": "array",
"items": {
"type": "integer"
},
"if": {
"properties": {
"period": {
"properties": {
"label": {
"pattern": "^\\d{4}_(01|03|05|07|08|10|12)$"
}
}
}
}
},
"then": {
"maxItems": 31
},
"else": {
"if": {
"properties": {
"period": {
"properties": {
"label": {
"pattern": "^\\d{4}_(04|06|09|11)$"
}
}
}
}
},
"then": {
"maxItems": 30
},
"else": {
"if": {
"properties": {
"period": {
"properties": {
"label": {
"pattern": "^\\d{4}_02$"
}
}
}
}
},
"then": {
"if": {
"properties": {
"period": {
"properties": {
"label": {
"pattern": "^(\\d{2}([02468][048]|[13579][26])|(\\d{2}([02468][1235679]|[13579][01345789])))_02$"
}
}
}
}
},
"then": {
"maxItems": 29
},
"else": {
"maxItems": 28
}
}
}
}
}
},
"required": [
"period"
],
"additionalProperties": false
}
Example data (this should not validate):
{
"period": {
"label": "2024_02"
},
"days": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
}
I've tested this using JSON Schema Validator https://www.jsonschemavalidator.net/ and it always validates regardless of the value of label. What is wrong here and how to correct it?
Upvotes: 0
Views: 29
Reputation: 3254
You were fairly close, but the if, then
, must be defined at the highest possible level to drill into each subschema. In other words, {"if": { "properties": {"period"...
cannot evaluate the property period
within the days
sibling schema.
If you have more than one if, then
condition, it's advised to wrap them in an allOf
to make sure they are all evaluated
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"period": {
"type": "object",
"properties": {
"label": {
"type": "string"
}
},
"required": [
"label"
]
},
"days": {
"type": "array",
"items": {
"type": "integer"
}
}
},
"allOf": [
{
"$ref": "#/definitions/label-pattern-31dayMonths"
},
{
"$ref": "#/definitions/label-pattern-30dayMonths"
},
{
"$ref": "#/definitions/label-pattern-february"
}
],
"required": [
"period"
],
"additionalProperties": false,
"definitions": {
"label-pattern-31dayMonths": {
"if": {
"properties": {
"period": {
"properties": {
"label": {
"pattern": "^\\d{4}_(01|03|05|07|08|10|12)$"
}
}
}
}
},
"then": {
"properties": {
"days": {
"maxItems": 31
}
}
}
},
"label-pattern-30dayMonths": {
"if": {
"properties": {
"period": {
"properties": {
"label": {
"pattern": "^\\d{4}_(04|06|09|11)$"
}
}
}
}
},
"then": {
"properties": {
"days": {
"maxItems": 30
}
}
}
},
"label-pattern-february": {
"if": {
"properties": {
"period": {
"properties": {
"label": {
"pattern": "^\\d{4}_02$"
}
}
}
}
},
"then": {
"if": {
"properties": {
"period": {
"properties": {
"label": {
"pattern": "^(\\d{2}([02468][048]|[13579][26])|(\\d{2}([02468][1235679]|[13579][01345789])))_02$"
}
}
}
}
},
"then": {
"properties": {
"days": {
"maxItems": 29
}
}
},
"else": {
"properties": {
"days": {
"maxItems": 28
}
}
}
}
}
}
}
This fails as expected, with more than the maxItems
allowed.
{
"period": {
"label": "2024_02"
},
"days": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
}
If you remove the last two entries, the schema passes after matching the february
conditional statement then
condition.
p.s. I made up the schema naming in definitions
just to clean up the readability
Upvotes: 1