Skip to content

zod-rs

A Zod-inspired Rust validation library. Composable schemas, derive macros, detailed errors, and TypeScript codegen.

Type-safe validation

Full type safety with compile-time guarantees. Define schemas once, get validated and typed data.

Zero dependencies

Lightweight core with optional integrations for Axum and other web frameworks.

Rich error messages

Detailed validation errors with full path information, plus i18n support.

Derive macros

Automatically generate schemas from Rust structs and enums with #[derive(ZodSchema)].

TypeScript codegen

Generate TypeScript Zod schemas from Rust types with #[derive(ZodTs)].

Composable schemas

Build complex validation rules from simple primitives. Reuse schemas across your codebase.

use serde_json::json;
use zod_rs::prelude::*;
fn main() {
let schema = object()
.field("name", string().min(2).max(50))
.field("email", string().email())
.field("age", number().min(0.0).max(120.0).int());
let data = json!({
"name": "Alice",
"email": "[email protected]",
"age": 25
});
match schema.safe_parse(&data) {
Ok(value) => println!("Valid: {:?}", value),
Err(errors) => println!("Invalid: {}", errors),
}
}

zod-rs is a Rust validation library that validates data at runtime using composable schemas. You define rules with primitives like string(), number(), object(), and array(), compose them into complex schemas, and call safe_parse() to validate input — getting back either a typed struct or detailed errors with the full path to each failing field (e.g. user.addresses[0].zip).

  1. Define a schema — use builder methods (string().email().min(5)) or derive it from a struct with #[derive(ZodSchema)]
  2. Validate input — call safe_parse(&json_value) or validate_and_parse(&json_value) to validate and deserialize in one step
  3. Handle errors — every error includes the full field path, a human-readable message, and i18n support

Unlike attribute-only validators such as validator and garde, zod-rs schemas are values: you can build them at runtime, store them, compose them, and reuse them across your codebase. This makes zod-rs ideal for validating API request bodies, configuration files, webhook payloads, and any untrusted input where the schema may not be known at compile time.

  • Validates raw JSON directly — no need to deserialize first; parsing and validation happen in one step
  • Runtime schema composition — build, combine, and reuse schemas dynamically, not just at compile time
  • Full-path error messages — errors report the exact location of failures in nested data (user.profile.email)
  • TypeScript codegen — generate matching TypeScript Zod schemas from Rust types so frontend and backend validate with the same rules
  • Built-in i18nlocalize error messages with built-in locale support
  • Framework integration — built-in Axum support with structured error responses

For a detailed comparison, see Choosing a Rust Validation Library or the migration guides from validator and garde.

New to data validation in Rust? These guides cover the most common use cases:

How is zod-rs different from the validator crate?

Section titled “How is zod-rs different from the validator crate?”

The validator crate checks structs you have already deserialized. zod-rs validates raw JSON values directly, so parsing and validation happen in one step, schemas can be built and composed at runtime, and errors carry the full path to the failing field. See the full comparison and migration guide.

Yes. Schemas validate serde_json::Value, the derive macro honors #[serde(rename)] and #[serde(rename_all)], and enum validation matches serde’s externally tagged JSON format.

Can I validate HTTP request bodies in Axum?

Section titled “Can I validate HTTP request bodies in Axum?”

Yes. Enable the axum feature to validate request bodies with a zod-rs schema and return structured validation errors from your handlers. See the Axum integration guide.

Can I share validation rules between Rust and TypeScript?

Section titled “Can I share validation rules between Rust and TypeScript?”

Yes. The ZodTs derive macro and the zod-rs-ts CLI generate TypeScript Zod schemas from your Rust types, so the frontend and backend validate with the same rules. See the fullstack validation guide.

Add #[derive(ZodSchema)] to your struct and annotate fields with #[zod(email)], #[zod(min_length(3))], or other validation rules. Then call validate_and_parse() to validate JSON input and get a typed struct in one step, with full-path error messages for every failing field. See the struct validation guide and the attributes reference.

It depends on your use case. The validator crate and garde are best for checking structs you have already deserialized. zod-rs is best when validation starts at a boundary — API requests, config files, webhooks — because it validates raw JSON directly, composes schemas at runtime, generates TypeScript Zod schemas, and reports full-path errors. See the detailed comparison.