I'm using AJV to validate a JSON based on some JSON Schema.
I'd like to define a custom keyword that applies validation from a subschema based on some condition of the data (basically a more flexible version of discriminator
).
For example:
{
"mykeyword": {
"even": {
"properties": {
"p": {"type": "string"}
}
},
"odd": {
"properties": {
"p": {"type": "number"}
}
}
}
"type": "object",
"properties": {
"n": "number"
}
}
I'd like to figure out how to implement the following logic:
if ( data.n % 2 == 0 )
validate(schema.even, data)
else
validate(schema.odd, data)
Meaning selecting the right schema to validate against based on some condition.
It seems to be possible using the code
custom keyword definition but their documentation only provides trivial examples.
For some context on my actual use case: the schema has its definitions in oneOf
, I only want to validate the correct one but the provided discriminator
is not enough to figure out which schema to validate. Not doing this causes AJV to return errors for every possible schema in oneOf
which I don't want.
For what it's worth, I managed to write a keyword using validate
rather than code
. That looks something like this:
{
keyword: "mykeyword",
validate: function validate_mykeyword(schema, data, parent_schema, data_cxt)
{
var sub_schema = get_schema_id_based_on_condition(data, schema);
if ( sub_schema === undefined )
{
validate_mykeyword.errors = [{
message: "Custom error",
instancePath: data_cxt.instancePath,
parentSchema: parent_schema,
}];
return false;
}
var validate = this.getSchema(sub_schema);
if ( !validate(data, data_cxt) )
{
validate_mykeyword.errors = validate.errors;
return false;
}
return true;
}
}
Some things worth noting: validate
must be a named function so you can get this
value properly (which will be set to the Ajv
instance) and to set errors which need to be a property of the function itself.