สำหรับวันนี้เราจะมาอยู่กับ Library เจ๋ง ๆ ที่ชื่อว่า Zod สำหรับเอามาเช็คดูว่าค่าที่ส่งมานั้นถูกต้องตามที่เราได้กำหนดไว้หรือป่าว ถ้าถูกก็จะทำงานได้ แต่ถ้าไม่ถูกต้องมันก็จะแจก Error มาให้ ทำให้ลดโอการที่จะเกิดบั๊กจากข้อมูลที่ใส่มาไม่ถูกต้อง โดยในบทความนี้ จะพามาดูวิธีการใช้งานแบบ Step by step กันเลย ถ้าพร้อมแล้วเราไปลุยกันเลย!
Zod คืออะไร?
ก่อนอื่นมาทำความรู้จักกับ Zod ก่อนโดยมันคือ TypeScript Library ที่ใช้สำหรับตรวจสอบว่าข้อมูลที่รับมาและส่งออกไปนั้นถูกต้องตามที่เราต้องการรึป่าว เรียกง่าย ๆ ว่าเป็น Lib สำหรับการทำ Data Validation นั่นแหละ
ขั้นตอนการสร้าง API ที่ใช้ Zod โดยตัวอย่างนี้จะใช้ร่วมกับ Express.js และ TypeScript ก่อนอื่นเราก็จะต้องสร้างโปรเจกต์ขึ้นมาก่อน โดยการใช้คำสั่ง
mkdir express-zod-workshop
cd express-zod-workshop
npm init -y
JavaScriptแล้วก็ติดตั้ง package สำหรับโปรเจกต์นี้
npm install express body-parser zod
npm install --save-dev typescript @types/node @types/express ts-node nodemon
JavaScriptโปรเจกต์นี้เป็น TypeScript เราจะต้องสร้างไฟล์ tsconfig.json โดยสามารถสร้างไฟล์พร้อมค่าเริ่มต้นได้ด้วยคำสั่ง เมื่อไฟล์ tsconfig.json มาแล้ว ให้เราลองไปเช็คดูหน่อยว่า strict ตั้งเป็น true แล้วหรือป่าว เพื่อที่เราจะได้ใช้ความสามารถในการเช็ค Type ของ TypeScript ได้ด้วย
npx tsc --init
JavaScriptต่อมาก่อนที่จะเริ่มเขียนโค้ดกัน เราจะต้องมาสร้างโครงสร้างของโปรเจกต์หน้าตาแบบนี้ก่อน
ต่อมาให้ไปที่จุดเริ่มต้นของการรันแอป โดยเราจะใช้ไฟล์ src/index.ts ทำการเรียกใช้ express body-parser สำหรับจัดการ JSON และกำหนด route โดยตอนนี้จะมีแค่เส้น /api/user ให้เชื่อมโยงกับ userRouter ที่จัดการฟังก์ชันการทำงานของ API ที่เกี่ยวข้องกับผู้ใช้
import express from 'express';
import bodyParser from 'body-parser';
import userRouter from './routes/userRoutes';
const app = express();
const PORT = 3000;
app.use(bodyParser.json());
app.use('/api/user', userRouter);
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
JavaScriptต่อมาเราจะมาสร้าง Zod Schemas เอาไว้สำหรับจัดการข้อมูล โดย Zod Schemas จะเป็นโครงสร้างที่ใช้กำหนดรูปแบบข้อมูล ) ที่เราต้องการในโปรเจกต์เพื่อช่วยในการสร้างและตรวจสอบความถูกต้องของข้อมูล โดยเราจะเขียนไว้ในโฟลเดอร์ src/schemas สร้างไฟล์ userSchemas.ts
import { z } from 'zod';
export const userRegistrationSchema = z.object({
username: z.string().min(3, "Username must have at least 3 characters"),
email: z.string().email("Invalid email address"),
password: z.string().min(8, "Password must have at least 8 characters"),
});
export const userLoginSchema = z.object({
username: z.string(),
password: z.string().min(8, "Password must have at least 8 characters"),
});
JavaScriptโดยโค้ดนี้จะเห็นได้ว่าเราใช้ Zod ในการสร้าง Schema ในการเช็คข้อมูล เราจะกำหนด Schema เอาไว้เลยว่าข้อมูลที่เข้ามาใน user registration และ user login จะต้องเป็นแบบไหน เช่นในโค้ดบอกว่า
userRegistrationSchema มีการกำหนดว่า username ต้องเป็นสตริงที่มีความยาวอย่างน้อย 3 ตัวอักษร, email ต้องเป็นอีเมลที่ถูกต้องตามรูปแบบ, และ password ต้องมีความยาวอย่างน้อย 8 ตัวอักษร
ส่วน userLoginSchema เป็น Schema ที่ใช้สำหรับตรวจสอบข้อมูลการล็อกอิน โดยกำหนดว่า username ต้องเป็นสตริง และ password ต้องมีความยาวอย่างน้อย 8 ตัวอักษร แล้วถ้าถามว่ามีอะไรที่เราต้องรู้ในการกำหนด Schema บ้าง
import { z } from 'zod';
const stringSchema = z.string(); // ค่าเป็น string
const numberSchema = z.number(); // ค่าเป็น number
const booleanSchema = z.boolean(); // ค่าเป็น boolean
const dateSchema = z.date(); // ค่าเป็น Date object
JavaScriptการเพิ่มข้อกำหนด (Constraints)
String
const schema = z.string()
.min(3, "Must be at least 3 characters") // ความยาวขั้นต่ำ
.max(10, "Must be at most 10 characters") // ความยาวสูงสุด
.email("Invalid email address") // ต้องเป็นอีเมล
.url("Invalid URL"); // ต้องเป็น URL
JavaScriptNumber
const schema = z.number()
.min(0, "Must be at least 0") // ค่าน้อยสุด
.max(100, "Must be at most 100") // ค่าสูงสุด
.int("Must be an integer"); // ต้องเป็นจำนวนเต็ม
JavaScriptArray
const schema = z.array(z.string()); // อาร์เรย์ที่มี string
const schemaWithMinMax = z.array(z.number()).min(1).max(5); // อาร์เรย์ของ number ที่มี 1-5 รายการ
JavaScriptObject
const schema = z.object({
username: z.string().min(3),
age: z.number().min(18),
email: z.string().email(),
});
JavaScriptกลับมาที่ไฟล์ของเราต่อมาเราจะมาสร้าง Middleware สำหรับ Validation ให้ไปที่ โฟลเดอร์ src/middleware สร้างไฟล์ validationMiddleware.ts แล้วเขียนโค้ดเข้าไปดังนี้
import { Request, Response, NextFunction } from 'express';
import { z, ZodError } from 'zod';
export function validateData(schema: z.ZodObject<any>) {
return (req: Request, res: Response, next: NextFunction) => {
try {
schema.parse(req.body);
next();
} catch (error) {
if (error instanceof ZodError) {
const errorMessages = error.errors.map(err => ({
path: err.path.join('.'),
message: err.message,
}));
res.status(400).json({ error: "Invalid data", details: errorMessages });
} else {
res.status(500).json({ error: "Internal Server Error" });
}
}
};
}
JavaScriptโดย Middleware นี้จะหยุดการทำงานหากข้อมูลไม่ตรงกับ Schema และบอก Error ที่ตั้งไว้ออกมา เสร็จแล้วเราก็สามารถเรียกใช้ Middleware ใน Route ได้โดยไปที่ โฟลเดอร์ src/routes สร้างไฟล์ userRoutes.ts
import express from 'express';
import { validateData } from '../middleware/validationMiddleware';
import { userRegistrationSchema, userLoginSchema } from '../schemas/userSchemas';
const userRouter = express.Router();
userRouter.post('/register', validateData(userRegistrationSchema), (req, res) => {
res.json({ message: "User registered successfully!", data: req.body });
});
userRouter.post('/login', validateData(userLoginSchema), (req, res) => {
res.json({ message: "User logged in successfully!", data: req.body });
});
export default userRouter;
JavaScriptเท่านี้ก็เรียบร้อย! ตอนนี้ /api/user/register และ /api/user/login พร้อมใช้งานแล้ว รันเซิร์ฟเวอร์
npx ts-node-dev src/index.ts
JavaScriptแล้วลองยิง API ผ่าน Postman ได้เลย ตัวอย่างเส้น /api/user/register ด้วย POST Method แนบข้อมูลไปใน Body ดังนี้
{
"username": "john",
"email": "john@example.com",
"password": "mypassword"
}
JavaScriptถ้าข้อมูลถูกก็จะได้ข้อความว่า User registered successfully!
แต่ถ้าใส่ข้อมูลผิด Middleware ก็จะเอา Error มาถวายในทันที555
และนี่ก็เป็นตัวยอย่างการทำ API พร้อมกับการทำ Validation ไปพร้อม ๆ กันผ่าน Lib ของ TypeScript ยอดฮิตอย่าง Zod นั่นเอง