Schema Validation
Validation is the core pillar of Adapters. You can build validation schemas programmatically using builder types, or let the procedural macros generate them automatically.
Declarative Attributes (#[derive(Schema)])
When deriving Schema on your structures, you can use the #[schema(...)] attribute to specify validation constraints. The macro supports a rich set of rules:
String Constraints
min_length = <usize>: The string must contain at least N characters.max_length = <usize>: The string must contain at most M characters.non_empty: The string cannot be empty (equivalent tomin_length = 1).email: Enforces a standard RFC 5322-compliant email format check.url: Enforces a valid absolute URL format check.regex = "<pattern>": Matches the string against a custom regular expression.
Numeric Constraints
min = <number>: Value must be greater than or equal to N.max = <number>: Value must be less than or equal to M.positive: Enforces that the number is strictly greater than zero (> 0).negative: Enforces that the number is strictly less than zero (< 0).non_zero: Fails validation if the number is exactly 0.
Structural Controls
strict: Enforces strict type checking. When true, types like numbers will not be coerced from strings.optional: Declares the field as optional (permits Null values).default = <expression>: Applies a default value if the key is missing in the source payload.
Programmatic Schema Building
If you need to construct schemas dynamically at runtime, use our highly expressive builder APIs:
#![allow(unused)] fn main() { use adapters::prelude::*; use adapters::schema::{ObjectSchema, StringSchema, IntegerSchema}; let schema = ObjectSchema::new() .field("username", StringSchema::new().required().non_empty().alphanumeric()) .field("age", IntegerSchema::new().required().min(18).max(99).positive()) .field("balance", IntegerSchema::new().required().non_zero()) .strict(); // Rejects unknown object keys // Validate a dynamic Value representation let payload = Value::Null; // or Value::Object(...) let result = schema.validate(&payload, "root"); }
Nested Schema Validation
Adapters natively supports recursive validation of complex nested structures. When a structure derives Schema, its schema definition incorporates the schema of any sub-structures that also implement SchemaProvider.
For example, when validating a parent struct like User, any nested objects (e.g. Address) will be fully validated against their own schemas. Any validation failures in the nested child are reported with correct dot-notation paths (e.g., address.city or address.zip_code).
#![allow(unused)] fn main() { use adapters::prelude::*; #[derive(Schema, Debug)] struct Address { #[schema(min_length = 3)] city: String, country: String, } #[derive(Schema, Debug)] struct User { name: String, address: Address, // Automatically delegates validation to Address::schema()! } }
If you attempt to parse a payload where address.city is only two characters long, the validation engine will fail and report address.city as the failing field path.