According to the specification (http://json-schema.org/schema) there is no mutual exclusion among schema keywords.
For example I could create the following schema:
{
"properties" : {
"foo" : {"type" : "string"}
}
"items" : [
{"type" : "integer" },
{"type" : "number" }
]
}
Would this schema validate against both objects and arrays?
If so it would imply an "OR" relationship between keyword.
But if we consider the following schema:
{
"anyOf" : [
{ "type" : "string",},
{ "type" : "integer"}
]
"not" : {
{ "type" : "string",
"maxLength" : 5
}
}
}
The most practical way to interpret it would be an "AND" relationship between anyOf and not keywords.
I could not find any indication in the draft v4 on how keywords logically interact. Can anyone point me to a documentation/standard that would answer this question?
Keywords are always an "AND" relationship. Data must satisfy all keywords from a schema.
The properties
and items
keywords don't specify the type of the object (you have to use type
for that). Instead, they only have meaning for particular types, and are ignored otherwise. So properties
actually means:
If the data is an object, then the following property definitions apply...
This means that {"properties":{...}}
will match any string, because properties
is ignored for values that aren't objects. And items
actually means:
If the data is an array, then the following item definitions apply...
So the AND combination looks like:
(If the data is an object, then properties
applies) AND (if the data is an array, then items
applies)
As the spec clearly dictates, some keywords are only relevant for one particular type of JSON value, or all of them.
So, for instance, properties
only applies if the JSON value you validate is a JSON Object. On any JSON value which is NOT an object, it will not apply (another way to understand it is that if the JSON value to validate is not a JSON Object, validation against this keyword will always succeed).
Similarly, items
will only apply if the JSON value is a JSON Array.
Now, some other keywords apply for all types; among these are enum
, allOf
, anyOf
, oneOf
, type
. In each case, the validation rules are clearly defined in the specification.
In short: you should consider what type of value is expected. The easiest way to force a value to be of a given type in a schema is to use type
, as in:
"type": "integer"
BUT this keyword will nevertheless be applied INDEPENDENTLY of all others in the validation process. So, this is a legal schema:
{
"type": "integer",
"minItems": 1
}
If an empty JSON Array is passed for validation, it will fail for both keywords:
type
because the value is not an array;
minItems
because the value is an array but it has zero elements, which is illegal for this particular keyword since it expects one element in the array at least.
Note that the result of validation is totally independent of the order in which you evaluate keywords. That is a fundamental property of JSON Schema. And it is pretty much a requirement that it be so, since the order of members in a JSON Object is irrelevant ({ "a": 1, "b": 2 }
is the same JSON Object as { "b": 2, "a": 1 }
).
And of course, if only ONE keyword causes validation to fail, the whole JSON value is invalid against the schema.