Rusdantic
Rusdantic is a high-ergonomics data validation and serialization framework for Rust, inspired by Python's Pydantic. It bridges the gap between Serde and validation crates like validator / garde into a single, unified derive macro.
Why Rusdantic?
In the Rust ecosystem, validation is fragmented across multiple crates. Rusdantic unifies serialization, deserialization, and validation into one derive macro:
- One Derive, Three Traits:
#[derive(Rusdantic)]generatesSerialize,Deserialize, andValidate - Validate-on-Deserialize: Invalid structs never exist in memory when using
from_json() - Path-Aware Errors: Get precise error paths like
user.addresses[0].zip_code - 7 Built-in Validators:
length,range,email,url,pattern,contains,required - Custom Validators: Field-level and struct-level cross-field validation
- Serde Compatible: Works with
rename_all,deny_unknown_fields, and other serde attributes - JSON Schema: Generate Draft 2020-12 / OpenAPI 3.1 schemas from your types
- PII Redaction:
#[rusdantic(redact)]hides sensitive data in Debug output - Sanitizers:
trim,lowercase,uppercase,truncateduring deserialization - Partial Validation: Validate subsets of fields for PATCH endpoints
- Zero-Cost: Validation logic is monomorphized at compile time
Quick Start
Add rusdantic to your Cargo.toml:
[]
= "0.1.0"
Basic Usage
use *;
Nested Structs with Path-Aware Errors
// Errors include full paths: "addresses[1].zip_code: must match pattern..."
Custom Validators
// Cross-field validation
Sanitizers
PII Redaction
JSON Schema Generation
let schema = json_schema;
// Produces:
// {
// "$schema": "https://json-schema.org/draft/2020-12/schema",
// "title": "User",
// "type": "object",
// "properties": {
// "username": { "type": "string", "minLength": 3, "maxLength": 20 },
// "email": { "type": "string", "format": "email" },
// "age": { "type": "integer" }
// },
// "required": ["username", "email", "age"]
// }
Partial Validation (PATCH endpoints)
let user = User ;
// Only validate specific fields
user.validate_partial?;
Feature Comparison
| Feature | serde + validator | serde + garde | Rusdantic |
|---|---|---|---|
| Setup | 3+ crates | 2+ crates | 1 crate |
| Validate on deser | No (invalid structs in memory) | No | Yes |
| Error paths | Manual (serde_path_to_error) |
Built-in | Built-in |
| Type coercion | serde_with per-field |
No | Configurable |
| Sanitizers | No | No | Built-in |
| JSON Schema | Separate (schemars) |
No | Built-in |
| PII Redaction | No | No | Built-in |
| Partial validation | No | No | Built-in |
Available Validators
| Attribute | Description | Example |
|---|---|---|
length(min, max) |
String/collection length | #[rusdantic(length(min = 1, max = 255))] |
range(min, max) |
Numeric bounds | #[rusdantic(range(min = 0, max = 100))] |
email |
Email format | #[rusdantic(email)] |
url |
URL format | #[rusdantic(url)] |
pattern(regex) |
Regex match | #[rusdantic(pattern(regex = "^[a-z]+$"))] |
contains(value) |
Substring check | #[rusdantic(contains(value = "@"))] |
required |
Option must be Some | #[rusdantic(required)] |
custom(function) |
Custom validator | #[rusdantic(custom(function = my_fn))] |
nested |
Recursive validation | #[rusdantic(nested)] |
Available Sanitizers
| Attribute | Description |
|---|---|
trim |
Strip leading/trailing whitespace |
lowercase |
Convert to lowercase |
uppercase |
Convert to uppercase |
truncate(max = N) |
Truncate to N characters |
Struct-Level Attributes
| Attribute | Description |
|---|---|
rename_all = "camelCase" |
Rename all fields (serde-compatible) |
deny_unknown_fields |
Reject unknown JSON keys |
custom(function = fn) |
Cross-field validation |
Contributing
We welcome contributions! Please see our CONTRIBUTING.md for details.
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.
Inspired by the ergonomics of Pydantic, built for the safety of Rust.