"missing" or "defaultProperties" annotation keyword #867
Description
The "default" keyword is one of the most misused & abused annotation keywords due to consequences of how JSON Schema works.
It is frequently assumed that if a property in an instance document is missing, the "default" keyword lets you create that property and fill in that value as if it has the same behavior.
But this is not actually the case. The biggest reason is the "default" keyword does not produce an annotation unless the property exists in the instance in the first place... defeating the point.
The "default" keyword is mostly useful for user interface and IDE work, where a user indicates they want to create a value, and so the "default" keyword can provide a sensible initial default in these cases. For example:
-
A user creates a new record in a document database (like a MongoDB collection). The interface creates an instance of the schema, reading the "default" keyword to provide a value; instead of creating a blank document (which is invalid JSON).
-
A user in an IDE is typing
{ "name":
and then tab-completes in the default value, an empty string (as opposed to e.g. a number, or another object).
However, all the time, users seem to think you can substitute in the "default" value for a missing one:
- draft7 schema incorrect in the definition of the "not" property? #858
- https://stackoverflow.com/questions/60433669/how-to-add-default-values-from-json-schema-to-json-document-in-java/60443802 (see my answer for more details on why "default" probably doesn't do what you think it does)
This also seemed sensible to me until I realized that "default" doesn't produce an annotation if the instance is absent.
I'm proposing a keyword that does mean exactly this: it means "if the instance is an object, and it is missing any of the given properties, the behavior will be the same as if it were defined with the specified value".
Example schema:
{
"missing": {
"port": 80
},
"properties": {
"port": { "type":"integer" }
}
}
This would allow implementations to infer that this:
{ }
will behave the same as this:
{ "port": 80 }
Some implementations or tools might even offer a way to return a copy of the instance with these values filled in. This would be useful for applications that want to both validate user input, and fill in defaults; instead of having to perform these as separate operations.