What version of Ajv you are you using?
5.5.2
What problem do you want to solve?
I'm dynamically generating an HTML form. The shape of later parts of the form depends on choices made in earlier fields. For example:
let schema = {
type: 'object',
oneOf: [{
properties: {
type: { type: 'string', enum: ['type-a', 'type-b'] },
value: { $ref: '#/definitions/stringList' }
},
required: ['type', 'value']
}, {
properties: {
type: { type: 'string', enum: ['type-c'] },
value: { $ref: '#/definitions/numberList' }
},
required: ['type', 'value']
}],
// ...
};
And say I have this value:
let obj = {
type: 'type-a',
value: []
};
Ajv is already doing the heavy lifting of matching the value to the schema, but in the end it only gives me a yes/no answer (yes, it matched). But I'd like to know what the schema for obj.value is, given that obj.type === 'type-a', so the UI can offer the proper fields, autocomplete options, etc.
What do you think is the correct solution to problem?
The correct solution is probably an option or separate method in ajv to generate a mapping from each sub-value in the original value to the sub-schema it matched against. Like:
let map = ajv.match(schema, obj);
assert(map.get(obj.value) === schema.definitions.stringList) // or something
I imagine this data is already available to ajv, just not exposed through the API, unless I'm missing something. I guess there may be unforeseen difficulties, but if this functionality is limited to schema-paths containing oneOf (as opposed to anyOf), it may be quite easy to implement if you already know the ajv source-code.
Will you be able to implement it?
I might give it a go at some point if no one else does. Though it's unlikely I could do this well without spending a bunch of time learning the ajv source-code. My hope is that this feature is already available somewhere and I just missed it, or that it is attractive enough and easy enough to implement that someone already familiar with the code will want to tackle it.
It鈥檚 a bit more complex than that as ajv doesn鈥檛 need to know which schema paths were matched (and it indeed doesn鈥檛 keep track of that). For oneOf for example it only tracks that some subschema succeeded and if more than one succeeded it fails straight away. You could use custom error processing with ajv-errors (to consolidate messages) and then on top of that create your own custom keyword that would look whether the current subschema passed. That鈥檚 probably clunky but it would do what you need. I think there could indeed be a property defined on validate function to collect JSON pointers of subschemas that contributed to the final success, but there will be some tricky things to pass this info between referenced subschemas that may be compiled to separate functions.
Also, there is still an open issue with some inconsistent reporting of schema paths when referenced subschemas are used - that probably needs to be improved as well.
So, I like the idea, but it鈥檚 not trivial.
Thanks for your reply!
I guess I was making bad assumptions based on how _I_ would implement json-schema validation, perhaps naively, with a simultaneous depth-first traversal of the trees, using a recursive function that distinguishes on shape. I wouldn't be keeping track of matched paths, as such, but they would still be on the call stack. It wouldn't require too many additional lines of code to then keep a record of every successful match, and upon encountering a mismatch, discard the current subtree of matches (rooted just below the nearest oneOf). Does ajv work fundamentally differently?
You mention one or two ways I could 'hack' this feature on top of the existing library? I'd like to try that. Could you possibly be a bit more specific, to help me get started? If it makes a difference, assume that my schema contains no $refs, because I can easily resolve those beforehand (there are no ref-cycles).
I'd like to throw my hat in the ring and say that actually being able to get the info on why a schema was validated as correct would be useful.
Actually, this is related to a problem I have: I want to know when part of a schema matches. I think the solution to my problem would also solve THIS problem.
Basically what I want is an "on" method that has two arguments: a "path" to the part of the schema I care about, and a function to call when that part matches (e.g. when the matcher returns from it with a "success" status, which it might do repeatedly for different parts of the schema, and whether or not the entire schema validation fails).
So to address the problem raised by this issue, you could use a bunch of "on" rules to collect the information you wanted as the validation progressed. This might be aided by passing in extra data to the on function as optional (extra) parameters, like the part of the data that matched.
closing this issue, it is better represented in https://github.com/epoberezkin/ajv/issues/902
Most helpful comment
I'd like to throw my hat in the ring and say that actually being able to get the info on why a schema was validated as correct would be useful.