JSON Body Validation
Basic JSON Validation
Section titled “Basic JSON Validation”Validate JSON request bodies using zValidatorYelix with the 'json' source:
import { YelixHono } from '@yelix/hono';import { zValidatorYelix, type ZInfer } from '@yelix/zod-validator';import { z } from 'zod';
const app = new YelixHono();
app.post( '/users', zValidatorYelix('json', z.object({ name: z.string(), email: z.email(), age: z.number().int().positive(), })), (c) => { // ZInfer provides full type safety const { name, email, age }: ZInfer<typeof z.object({ name: z.string(), email: z.email(), age: z.number().int().positive(), })> = c.req.valid('json' as never); return c.json({ message: 'User created', name, email, age }); });Accessing Validated Data
Section titled “Accessing Validated Data”After validation, access the validated data using c.req.valid(). For type safety, use the ZInfer helper type:
import { zValidatorYelix, type ZInfer } from '@yelix/zod-validator';import { z } from 'zod';
const userSchema = z.object({ name: z.string(), email: z.email(), age: z.number().int().positive(),});
app.post('/users', zValidatorYelix('json', userSchema), (c) => { // ZInfer provides full type safety - TypeScript knows the exact shape! const userData: ZInfer<typeof userSchema> = c.req.valid('json' as never);
// userData is properly typed as: { name: string; email: string; age: number } return c.json({ user: userData });});Note: The as never is needed due to TypeScript limitations with middleware type inference, but ZInfer ensures your data is fully type-safe, not any.
Complex Schemas
Section titled “Complex Schemas”You can use all Zod features for complex validation:
import { z } from 'zod';
// Nested objectsconst userSchema = z.object({ name: z.string().min(1), email: z.email(), address: z.object({ street: z.string(), city: z.string(), zipCode: z.string().regex(/^\d{5}$/), }), tags: z.array(z.string()),});
app.post('/users', zValidatorYelix('json', userSchema), handler);
// Optional fieldsconst updateSchema = z.object({ name: z.string().optional(), email: z.email().optional(), age: z.number().int().positive().optional(),});
app.patch('/users/:id', zValidatorYelix('json', updateSchema), handler);
// Union typesconst responseSchema = z.union([ z.object({ type: 'success', data: z.any() }), z.object({ type: 'error', message: z.string() }),]);Validation Rules
Section titled “Validation Rules”Use Zod’s validation methods to add constraints:
const schema = z.object({ // String validations name: z.string().min(1).max(100), email: z.string().email(), password: z.string().min(8).regex(/[A-Z]/).regex(/[0-9]/),
// Number validations age: z.number().int().positive().max(120), price: z.number().positive(),
// Array validations tags: z.array(z.string()).min(1).max(10),
// Date validations birthDate: z.string().datetime(),
// Custom validations username: z.string().refine( (val) => !val.includes(' '), { message: 'Username cannot contain spaces' } ),});Error Handling
Section titled “Error Handling”When validation fails, Yelix automatically returns a 400 Bad Request response with error details:
// If validation fails, the client receives:// Status: 400 Bad Request// Body: {// "success": false,// "error": {// "issues": [// {// "code": "invalid_type",// "expected": "string",// "received": "number",// "path": ["email"],// "message": "Expected string, received number"// }// ]// }// }With OpenAPI Documentation
Section titled “With OpenAPI Documentation”When used with Yelix’s OpenAPI system, the schema is automatically documented:
import { YelixHono, openapi } from '@yelix/hono';import { zValidatorYelix } from '@yelix/zod-validator';import { z } from 'zod';
const app = new YelixHono();
app.post( '/users', openapi({ summary: 'Create User', description: 'Creates a new user account', }), zValidatorYelix('json', z.object({ name: z.string().min(1), email: z.email(), age: z.number().int().positive(), })), (c) => { // ZInfer provides full type safety const data: ZInfer<typeof z.object({ name: z.string().min(1), email: z.email(), age: z.number().int().positive(), })> = c.req.valid('json' as never); return c.json({ message: 'User created', data }); });The request body schema will automatically appear in your OpenAPI documentation!