additionalProperties considers properties with "undefined" value as additional
What version of Ajv are you using? Does the issue happen if you use the latest version?
6.10.2
Ajv options object
// empty
{}
JSON Schema
{
"type": "object",
"additionalProperties": false,
"properties": {}
}
Sample data
The input is not a json but a javascript object with a key set to undefined, which is common when constructing objects with conditional fields:
{ "a": undefined }
Your code
const Ajv = require("ajv");
const ajv = new Ajv();
const v = ajv.compile({ type: "object", additionalProperties: false, properties: {} });
console.log(v({ a: undefined }), v.errors);
Validation result, data AFTER validation, error messages
$ node -p 'const Ajv = require("ajv"); const ajv = new Ajv(); const v = ajv.compile({ type: "object", additionalProperties: false, properties: {} }); console.log(v({ a: undefined }), v.errors)'
false [
{
keyword: 'additionalProperties',
dataPath: '',
schemaPath: '#/additionalProperties',
params: { additionalProperty: 'a' },
message: 'should NOT have additional properties'
}
]
What results did you expect?
I was expecting keys which are undefined to be ignored by additionalProperties: false
Are you going to resolve the issue?
This is related to several other issues - ajv behaviour was not specified for "undefined" properties, what is worse it is not consistent across all keywords.
e.g. #937, #1173 and PR #1176
I think it is dangerous to change the current behaviour without the major version change, that with a bit of luck may happen this year, and they should not be addressed in isolation, the behaviour for undefined for and some other JavaScript values outside of JSON should be defined consistently.
There are at least 4 possible approaches, in general, each has pros / cons:
- consider "undefined" properties as present (as now)
- consider "undefined" properties as absent
- make it dependent on yet one more option with default:
- present
- absent
I think that considering them as present by default with the option to consider them as absent is the best option, for several reasons:
- no change of default.
- aligned with JS view that differentiates between absent and undefined properties, and in many contexts it is important.
- allows to easier manage other contexts as in this issue.
With this approach, by default all type-specific keywords that validate values would ignore such properties, keywords that validate keys presence would account for them, and what type keyword should do is yet another question...
Hi @epoberezkin Thanks for following up - having an option for "considering undefined as absent" will work just fine for my case.
But I wonder - why do you think there is a good case for distinguishing the two cases in javascript? There is hardly any check that can differentiate between these cases other than ("a" in obj) or Object.getOwnPropertyNames(obj).includes("a") and any other literal comparison to null, undefined or assigning with/out a cast to boolean/string/etc will behave just the same. From my point of view when writing javascript code I try to avoid code that needs this distinction because it is almost too subtle and error prone.
This is just my 2cents - would be great to hear yours. Thanks!
related to #937
I just ran into this issue four years later, running ajv 8.17.1. I there a solution such as a flag to ignore undefineds?