Reputation: 792
Is there a way to create a repetition pattern for elements inside array of a JSON Schema document. I would like to use it in order to validate query produced by a query builder tool.
the part of the schema i currently use is
"complexCondition": {
"anyOf": [
{
"title": "Simple condition, e.x. X==0",
"type": "string"
},
{
"type": "array",
"items": [
{
"$ref": "#/complexCondition"
},
{
"type": "string", "enum": ["AND","OR"]
},
{
"$ref": "#/complexCondition"
}
],
"additionalItems": false
}
]
}
This allows me correct validation of query "conditionA && conditionB && conditionC" as
[[conditionA,"AND",conditionB],"AND",conditionC]
However, I would like to be able and validate documents where query is stored as
[conditionA,"AND",conditionB,"AND",conditionC]
and this to achievable for any number of conditions.
Upvotes: 3
Views: 1121
Reputation: 13635
In order to achieve what you intend to do you would need to define a rule for odd and even positions in an array, which can not be done for arrays of any length with json-schema.
If your expected number of query conditions is not going to grow ad infinitum, you could hard-code the first n positions in items keyword:
"items":[{"$ref":"#/condition},{"$ref":"#/operator"},{"$ref":"#/condition},{"$ref":"#/operator"} ... etc.]
In this case you still have the problem that you could define a wrong condition ending in "operator". Other option would be to make "oneOf" and build each posibility (this could be automated with a script, I guess you won't have expressions with 100 clauses...)
Anyway I find a bit strange to try to flatten a concept that is inherently recursive. How would you store this ( (A OR B) OR (C AND B))?
So If you can still rethink your desired serialization schema format I would suggest you to make a recursive approach. Something like:
"predicate" : {
"type" : "array",
"items" : {
"$ref" : "#/clause"
}
}
"clause" : {
"type" : "array",
"items" : [{
"$ref" : "#/condition"
}
],
"additionalItems" : {
"type" : "array",
"items" : [{
"$ref" : "#/operator"
}, {
"$ref" : "#/clause"
}
]
}
}
The generated string is more ugly, but parsing it would be fairly easy with a simple recursive function:
Simple condition:
[["condition1"]]
Simple Clause:
[["condition1",["OR",["condition2"]]]
Adding a clause at the same level
[["condition1",["OR",["condition2"]],["OR",["condition3"]]]
Add a clause to a child level
[["condition1",["OR",["condition2"]],["OR",["condition3", ["AND",["condition4"]]]]]
Upvotes: 2