It's worth noting that the Pydantic author stated he's rewriting parts of the validation in Rust for the next major release, with the aims of drastically improving performance.
I'm definitely interested in a simple type-safe validator library, but that planned performance boost is pretty tempting.
Quick follow-up that it looks like koda_validate is usually slower when validating dictionaries out of the box. Good news is it's clear where I should optimize, and that I'll add some benchmarks to this; optimistic Koda Validate can get faster than Pydantic. Thanks for the feedback!
- I haven't benchmarked this against pydantic... I guess I should!
- I would _hope_ that Koda Validate is at least competitive with Pydantic... because Koda Validate's main core improvement (IMO) is a consistent idea of what a validator is, validators in Koda Validate are actually much simpler than in Pydantic, meaning I would generally expect fewer instructions to be executed
- 3.11 (and 3.12) are both focused on performance. Both pydantic and Koda Validate might get some "free" performance boosts anyway (Thanks CPython devs!)
One thing that occurs to me: I don't want to have to describe my data in two places. Like how in the first example the dataclass Person has all the information needed to define the person_validator.
Thanks for the feedback! This tradeoff was considered a lot, and it's definitely a case of tradeoffs!
It's difficult to imagine a way of doing this that's as flexible but done with, let's say, a dataclass definition -- without being hacky. For instance, how do you handle non-string keys? What about strings keys that don't conform to instance properties? What about optional keys (not values)? How are types determined? One of the tricky things with Pydantic, for instance, is the way type annotations are contorted to be used for validation.
Some of the tradeoffs Koda Validate chooses in favor of here are:
- you don't have to install a plugin for type safety
- you can define any kind of target `Callable`; function, dataclass, other class, etc, so in some ways you have more flexibility
- if you want to use your validation target (let's say a class) elsewhere, you don't need to run validation every time it's instantiated.
- consistency at a typelevel for the all validators; dict, list, str, etc. This allows easy combination of validators
But yeah, I acknowledge the desire have a simple dataclass-like object. There is the potential that an abstraction may be made on top of what already exists to accomplish this, but the overall decision to not go that direction was made to keep consistency and avoid hacks.