Data Validation in Rust: Overview of Libraries and Frameworks
Data validation is a critically important stage in developing any application in Rust. The correctness of input data validation affects the security, stability, and predictability of the program. In the Rust ecosystem, there are several mature solutions for validation, each with its own features. In this article, we will take a detailed look at three main libraries: validator, garde, and validify, and also touch upon the built-in capabilities of serde.
1. The validator Library
validator is the most popular library for validating data structures. It provides attributes for annotating struct fields and automatically generating validation code via derive macros.
Installation
[dependencies]validator = { version = "0.18", features = ["derive"] }Usage Example
use validator::Validate;
#[derive(Debug, Validate)]struct User { #[validate(length(min = 3, max = 50))] username: String,
#[validate(email)] email: String,
#[validate(range(min = 18, max = 120))] age: u8,
#[validate(required)] phone: Option<String>,}
fn main() { let user = User { username: "Jo".to_string(), email: "invalid-email".to_string(), age: 15, phone: None, };
match user.validate() { Ok(_) => println!("Data is valid"), Err(errors) => { for (field, err) in &errors { println!("Error in field '{}': {:?}", field, err); } } }}Key Features of validator
- Built-in validators:
email,url,phone,credit_card,ip,must_match, and others. - String length, numeric range, and regular expression checks.
- Validation of nested structures via
#[validate(nested)]. - Support for custom validators via
custom.
2. The garde Library
garde is a modern and performant validation framework that positions itself as an alternative to validator with improved performance and a more flexible rule system.
Installation
[dependencies]garde = "0.21"Usage Example
use garde::Validate;
#[derive(Debug, Validate)]struct RegisterForm { #[garde(length(min = 3, max = 50))] username: String,
#[garde(email)] email: String,
#[garde(range(min = 18))] age: u32,
#[garde(ascii)] password: String,}
fn main() { let form = RegisterForm { username: "a".to_string(), email: "test".to_string(), age: 15, password: "password".to_string(), };
if let Err(errors) = form.validate() { for error in errors { println!("Error: {}", error.message); } } else { println!("Form is valid"); }}Advantages of garde
- High performance due to minimized allocations.
- Support for asynchronous validators.
- Rich set of built-in rules:
email,url,ip,phone,credit_card,pattern, and others. - Rule grouping and contextual validation.
- Ability to create custom validators with arbitrary logic.
3. The validify Library
validify is a framework that integrates with serde and provides a convenient way to validate data immediately after deserialization. This is especially useful when working with web frameworks (actix-web, axum).