Skip to main content
Build a signup model that accepts surrounding whitespace and a numeric age string, normalizes the email, fills optional values and rejects unknown fields.
10 minutesCore RydanticNo external services

1. Create a project

Add this dependency to the generated manifest:
Cargo.toml

2. Define the boundary

The Signup struct in the complete source below is the contract. #[derive(Model)] supplies parsing, serialization and schema generation. Coercion is explicit. Removing coerce makes the string "36" fail integer parsing; the JSON number 36 still works.

3. Copy the complete program

Put this source in src/main.rs. The same program lives at crates/rydantic/examples/data_contract.rs in the repository.
crates/rydantic/examples/data_contract.rs

4. Run both paths

From the repository checkout, run the equivalent example:
The accepted value has a trimmed name, lowercase email, integer age, empty tags and a null note. The next input produces four field errors:
Use each error’s loc or pointer() to associate it with a form field. code is the machine-readable category; message is a human-readable explanation. errors.to_json() exposes the structured errors for an application response.

5. Share the schema

Signup::json_schema(SchemaMode::Input) describes accepted input, including local-rule annotations for transformations. SchemaMode::Output describes the normalized serialized value. Both are JSON values that can be saved or passed to API tooling. Keep parsing at the application boundary: the generated schema describes structure, while the model runs trimming, coercion and its other runtime rules. See JSON Schema for portability details.

Try a change

Add "tags":["rust","api"] to the accepted input. Then change the minimum age to 21 and submit age 20. Compare the accepted output with the field path and constraint code in the rejected case.

Next: build a CRUD API

Use the same approach at an HTTP and database boundary.

More model examples

Explore enums, borrowed values and streaming JSON.