Description
JSON Schema validation has some interesting architectural properties. One of those properties is that keyword validations are stateless. They have no dependency on the results of the validation of any other keyword. This means keywords can be evaluated in any order, or even in parallel.
There are two exceptions to this rule: additionalProperties
and additionalItems
. additionalProperties
causes all kinds of problems and confusion when schema authors compose schemas. "additionalProperties": false
is used to disallow undefined properties (usually to detect typos), but it also makes it impossible to extend that schema using allOf
. This is why I always recommend that additionalProperties
not be used and that programs ignore undefined properties instead.
I think the only reason additionalItems
isn't similarly notorious is because it is rarely used. Fundamentally, it has the same problems.
I'm not sure if the architectural drift is the reason additionalProperties
and additionalItems
are problematic or if the problem is intrinsic in what they are trying to do. But, I don't think we should be tacking on additional functionally to solve the problems that additionalProperties
causes. Instead, we need to get rid of the cause of the problem and find a way to address the need of detecting typos in a way that doesn't violate the core architecture of JSON Schema. Until we have a good solution, I think it's fine to leave it up to the individual implementations to solve as they see fit. For example, json-schema-validator reports undefined properties as warnings. This seems like a perfectly good solution for most cases. It provides feedback to catch the kind of errors additionalProperties
is being used to detect without restricting the composablity of schemas.
I don't think we end up loosing anything by allowing validators to give feedback about undefined properties. However, additionalProperties
is also used for another purpose. It is used to describe an object with arbitrary keys whose values must all conform to the same schema. It is possible to describe this with patternProperties
using .*
as a key. What wouldn't be possible anymore is mixing these arbitrarily-named properties with named properties. I'm ok with that. I don't think it's a good idea to mix those things anyway. It seems a small thing to loose to get rid of something so problematic.
In case it's not clear what I mean ...
{
"type": "object",
"properties": {
"foo": { "type": "string" },
"bar": { "type": "string" },
"extraStuff": {
"type": "object",
"patternProperties": {
".*": { "type": "integer" }
}
}
}
}