silintzir
silintzir

Reputation: 792

JSON-Schema pattern repetition inside array

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

Answers (1)

jruizaranguren
jruizaranguren

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

Related Questions