jsonschema-rs icon indicating copy to clipboard operation
jsonschema-rs copied to clipboard

Combine validators

Open Stranger6667 opened this issue 4 years ago • 3 comments

If we have two or more validators, that can be applied to the same type, then we can sometimes combine them into a single validator to avoid extra loop iteration and a function call. Example:

{"minItems": 1, "maxItems": 3}

a combined validator implementation may look like this:

if let Value::Array(items) = instance {
    let length = items.len() as u64;
    return length > self.max_limit  || length < self.min_limit
}
true

Often validators go in groups, I think minimum / maximum is the most common combo. Maybe we can also group it with "type" validator into one. Not sure, but worth experimenting. Probably will slow down compilation a bit, but validation speed is more important

Note, that this concept is different from #63 because here we'll reduce the total iteration number, while #63 aims to eliminate matches on the input type. This idea also should reduce the number of match statements

and if we'll apply this to the extreme, then we can have all combinations for numeric, string, etc validators. Probably there could be a lot of duplication, but maybe it can be reduced by macros

Stranger6667 avatar May 22 '20 20:05 Stranger6667

cc @macisamuele as you are working on #63 - this issue might affect your implementation. If we'll go extreme, then we might not need iterations at all, only apply common grouped validator and type-specific grouped validator. What do you think?

Stranger6667 avatar May 22 '20 21:05 Stranger6667

It might be worth exploring.

Combining validator together would help performances but it will be an hit on maintenance cost as well. I would be careful on merging concepts together as the speedup might be negligible (few function calls if #63 helps centralising the type conversions)... But I'm not yet sure about it.

I would also consider the idea of creating equivalent and more effective schemas

{"anyOf": [	{"type": "string"}, {"type": "boolean"}]} 

Is equivalent to

{"type": ["string", "boolean"]} 

But this is even more sophisticated and probably harder to maintain

macisamuele avatar May 22 '20 21:05 macisamuele

There is another place where it can be reused - #46 , but it is probably too early to estimate :) I will do some experiments once I'll get there :)

And regarding your comment on creating simpler equivalents for schemas (basically #59). There is an awesome library where we can get a lot of inspiration https://github.com/Zac-HD/hypothesis-jsonschema. I use this library quite a lot in Schemathesis to generate valid data for Open API schemas and use it in tests

There is already a lot of logic implemented for schemas canonicalisation and we can re-implement it in Rust and the test suite is massive, which can also be reused

Stranger6667 avatar May 25 '20 14:05 Stranger6667