What version of Ajv are you using? Does the issue happen if you use the latest version?
Tried with 6.6.2/latest.
Ajv options object
{}
JSON Schema
{
"type": "object",
"properties": {
"A": { "type": "string" },
"hasA": { "type": "boolean" }
},
"if": { "properties": { "hasA": { "enum": [true] } } },
"then": { "required": ["A"] },
}
Sample data
{}
Or
{
"hasA": undefined
}
Your code
const Ajv = require('ajv');
const ajv = new Ajv;
const validate = ajv.compile(schema);
console.log(validate(data), validate.errors);
Validation result, data AFTER validation, error messages
[ { keyword: 'required',
dataPath: '',
schemaPath: '#/then/required',
params: { missingProperty: '.A' },
message: 'should have required property \'.A\'' } ]
What results did you expect?
The object to be valid.
Are you going to resolve the issue?
I look forward to it.
That is by design. The property with the value undefined is considered absent for the purpose of the validation (it will be absent if you stringify). An absent property is not validated against the schema somit passes. You need to use “required” keyword to require that property is present (either in or outside of “if”)
Hello,
(Sorry for the aggressive behavior later, bad morning...) Reopening this thread because I think this is a bug. Hope it's open for discussion
The problem here is not that the validation ignores properties that are undefined. The issue here is that The if/then clause evaluates to true (the then needs to be valid) even when the if clause is false. Here the expected behavior is that the if clause will evaluate to false given that the property doesn't exist and the then clause will be ignored.
I think you guys are using a function that returns true when it should return false given that the property does not exist.
Here the expected behavior is that the if clause will evaluate to false given that the property doesn't exist and the then clause will be ignored.
The "if" clause evaluates to true here because Ajv treats properties with the value "undefined" as absent, and with the absent property "if" clause is expected to evaluate to true - it is by the spec.
Thank you for your answer.
My point is that in all programming languages (and in boolean algebra in general), an if statement of null or undefined evaluates to false. Of course you can redefine that logic and create a specification that says that if(undefined || null) === true but that goes against how humans think and how programming languages are built.
Let's think about this example: if you're 2m tall, then you should play basketball, should you play basketball if you don't exist? Certainly not.
My proposal is that we review the specification so that if(undefined) === false in Ajv.
By your example it seems you are not taking into account that the ifThen is an exception to your rule (in terms of logic)
Ajv does not define the logic - it implements JSON schema specification that prescribes this behaviour. Proposal to change the specification should be addressed to JSON Schema org.
The solution is easy - if you want to require property existence in the “if” branch, you should use “required” keyword.
Also, about the example, you can look at the truthfulness table of boolean implication where false => false = true: http://sites.millersville.edu/bikenaga/math-proof/truth-tables/truth-tables.html
I agree that you can decide if whether or not it should evaluate to true since you can't take any decision on something that does not exist. If JSON schema has chosen this way then we must stick with it.
It would have been nice to not need the required on the schema because that would have allowed for branches where the required value is set whether an other field exist or not. With this way of doing things, the value will always be required even if the property does not exist.
Example of current behavior:
If you have an address, the postal code is required.I'm homeless and don't have an address but I need to fill in a postal code! (completely illogical)I'm homeless and don't have an address, therefore I ignore the postal code requirementWith your logic, the form needs an additional field are you homeless in order to decide if yes or not the address is required.
I'm surprised that this needs to be discussed as the example shows, it's not intuitive and leads to confusion. Even though I agree that if you don't have an address, you can't conclude anything about the postal code requirement.
I was about to post for this exact issue @darioAnongba
I agree, it should not think conditional fields are required by default. It would be great to have it as an option
It feels wrong to display an empty form, and see fields marked as "required" which actually might not be once other fields are changed.
Could I see an example of the work around?
@epoberezkin could you give an example of this work around? I don't follow what you mean.
Thanks.
FWIW, an example below
{
"type": "object",
"required": [
"countryOfBirth"
],
"properties": {
"countryOfBirth": {
"type": "string",
"enum": [
"au",
"nz"
]
},
"cityOfBirth": {
"type": "string"
}
},
"allOf": [
{
"if": {
"properties": {
"countryOfBirth": {
"enum": [
"au"
]
}
}
},
"then": {
"required": [
"cityOfBirth"
]
}
}
]
}
@yarnball your example is a bit different. For you, countryOfBirth is required so you cannot validate an object without that field. Given that you should never have an object without countryOfBirth, cityOfBirth will be validated correctly.
The problem we are talking about here is the case where countryOfBirth is not required and undefined. In that case, cityOfBirth will be mandatory, which is absurd (for me at least) as validation is doing exactly the opposite of what is expected (and there is no workaround from that except having multiple schemas)
@yarnball I understand and agree that JSON Schema specification can be confusing and counter intuitive, but this behaviour is correct according to the spec. So it’s important to understand it’s logic and how it works before you can apply it in any advanced validation scenarios.
Ajv issue tracker is not the right place though to discuss or to get support on using JSON Schema specification that Ajv implements.
Please submit this question to StackOverflow to get support on JSON Schema.
Could've kept it open. This behavior is really counter-intuitive.
Most helpful comment
Hello,
(Sorry for the aggressive behavior later, bad morning...) Reopening this thread because I think this is a bug. Hope it's open for discussion
The problem here is not that the validation ignores properties that are
undefined. The issue here is that Theif/thenclause evaluates to true (thethenneeds to be valid) even when theifclause isfalse. Here the expected behavior is that theifclause will evaluate to false given that the property doesn't exist and thethenclause will be ignored.I think you guys are using a function that returns true when it should return false given that the property does not exist.