aman.suhag
Thu Sep 26 2024
Schema Validation with Zod: Why and How?
When building APIs, validating the structure and content of incoming requests is crucial for security, consistency, and reliability. Using a library like
Why Validate?
1. Security: Ensure only well-formed data reaches your application, preventing injection attacks or bad data.
2. Consistency: Guarantees that the data has the correct shape, making it easier to work with.
3. Error Handling: Helps provide meaningful error messages when the validation fails.
Example: Standup Schema Validation
Using
Validating Incoming Data
In your API route, you can use
Key Benefits -
• Type Safety: With
• Automatic Error Handling: If the validation fails, you can easily catch errors and send meaningful feedback.
• Data Consistency: Guarantees that the incoming data adheres to a predefined structure, making your API more reliable and robust.
#zod #type-security #json
When building APIs, validating the structure and content of incoming requests is crucial for security, consistency, and reliability. Using a library like
zod
allows you to define schemas that describe the expected data format and then easily validate incoming data. Here’s how and why we use it in a Next.js API.Why Validate?
1. Security: Ensure only well-formed data reaches your application, preventing injection attacks or bad data.
2. Consistency: Guarantees that the data has the correct shape, making it easier to work with.
3. Error Handling: Helps provide meaningful error messages when the validation fails.
Example: Standup Schema Validation
Using
zod
, we can define a schema for our "standup" object and use it to validate incoming requests in our API route.
import { z } from "zod";
// Define a schema for the standup data
const standupSchema = z.object({
name: z.string().trim().nonempty(),
days: z.number().array().min(1).max(7),
time: z.string().datetime(),
postStandupTime: z.string().datetime(),
standupLead: z
.object({
name: z.string().trim().nonempty(),
id: z.string(),
})
.required(),
questions: z
.array(z.object({ text: z.string().min(1), isActive: z.boolean() }))
.min(1),
channel: z.object({
name: z.string().trim().nonempty(),
id: z.string(),
}),
members: z
.array(
z.object({
name: z.string().trim().nonempty(),
id: z.string(),
})
)
.min(1),
isActive: z.union([z.boolean(), z.undefined()]),
schedulerId: z.string().optional(),
timezone: z.string().min(1),
postType: z.string().min(1),
});
export type StandupDetail = z.infer;
Validating Incoming Data
In your API route, you can use
safeParse
to validate the request body against the schema. This ensures the data is valid before proceeding with further logic.
export async function PATCH(req: NextRequest) {
const body = await req.json();
// Validate the request body using the schema
const response = standupSchema.safeParse(body);
if (!response.success) {
const { errors } = response.error;
return NextResponse.json(
{ error: { message: "Invalid Payload", errors } },
{ status: 400 }
);
}
// If successful, extract the validated data
const {
name,
days,
time,
postStandupTime,
questions,
channel,
members,
isActive,
timezone,
standupLead,
postType,
}: StandupDetail = response.data;
// Proceed with your logic using the validated data
}
Key Benefits -
• Type Safety: With
zod
and TypeScript, you get strong typing, ensuring that the validated data has the expected shape.• Automatic Error Handling: If the validation fails, you can easily catch errors and send meaningful feedback.
• Data Consistency: Guarantees that the incoming data adheres to a predefined structure, making your API more reliable and robust.
#zod #type-security #json