iT邦幫忙

2025 iThome 鐵人賽

DAY 19
0
自我挑戰組

API 全攻略系列 第 19

Day 19:資料驗證與 Schema 設計

  • 分享至 

  • xImage
  •  

前言

在前一篇中,我們已經讓 Todo API 連接到 MongoDB,並能進行 CRUD 操作。但如果使用者傳入不正確的資料,例如 title 留空、日期格式錯誤,或是欄位根本不存在,這些都可能造成資料庫混亂。因此,今天我們要透過 Schema 設計資料驗證,確保 API 的穩定性與可靠性。


為什麼需要資料驗證?

  1. 確保資料完整性 :避免空值或不合理的輸入。
  2. 提升 API 穩定性 :不正確的請求會在進入資料庫前被攔截。
  3. 維護一致性 :欄位型別、長度、格式一致,方便後續處理。
  4. 降低錯誤成本 :比起後續修復,事前驗證更有效率。

使用 Mongoose Schema

我們在 Day 18 已經建立了 Todo Model。
今天,我們會在 Schema 中加入驗證規則。

// models/Todo.js
const mongoose = require('mongoose');

const todoSchema = new mongoose.Schema({
  title: {
    type: String,
    required: [true, 'Title is required'], // 必填欄位
    minlength: [3, 'Title must be at least 3 characters'], // 最小長度
    maxlength: [100, 'Title must be less than 100 characters'] // 最大長度
  },
  description: {
    type: String,
    maxlength: [500, 'Description too long'] // 限制字數
  },
  completed: {
    type: Boolean,
    default: false // 預設值
  },
  dueDate: {
    type: Date,
    validate: {
      validator: (value) => value > Date.now(), // 驗證日期必須在未來
      message: 'Due date must be in the future'
    }
  }
}, {
  timestamps: true // 自動產生 createdAt, updatedAt
});

const Todo = mongoose.model('Todo', todoSchema);
module.exports = Todo;

新增的驗證規則說明

  • required:必填
  • minlength / maxlength:字串長度限制
  • default:未提供時的預設值
  • validate:自訂驗證邏輯(例如截止日期必須大於今天)

在 Controller 中處理驗證錯誤

當使用者傳入不合法資料時,Mongoose 會拋出 ValidationError
我們需要在 Controller 中捕捉並回應使用者。

// routes/todos.js
const express = require('express');
const router = express.Router();
const Todo = require('../models/Todo');

// 建立 Todo
router.post('/', async (req, res) => {
  try {
    const todo = new Todo(req.body);
    await todo.save();
    res.status(201).json(todo);
  } catch (err) {
    if (err.name === 'ValidationError') {
      // 處理驗證錯誤
      return res.status(400).json({
        error: 'Validation Error',
        details: err.errors
      });
    }
    res.status(500).json({ error: 'Server Error' });
  }
});

module.exports = router;

測試資料驗證

正確請求

POST /api/todos
Content-Type: application/json

{
  "title": "Finish API project",
  "description": "Complete CRUD with validation",
  "dueDate": "2025-12-31"
}

回傳:

{
  "_id": "64xxxxxxx",
  "title": "Finish API project",
  "description": "Complete CRUD with validation",
  "completed": false,
  "dueDate": "2025-12-31T00:00:00.000Z",
  "createdAt": "...",
  "updatedAt": "..."
}

錯誤請求(缺少 title)

POST /api/todos
Content-Type: application/json

{
  "description": "Missing title"
}

回傳:

{
  "error": "Validation Error",
  "details": {
    "title": {
      "message": "Title is required"
    }
  }
}

進一步優化

  1. 欄位白名單 :只允許特定欄位被寫入,避免惡意傳入。
  2. 資料清理 :去除多餘空白、自動轉小寫等。
  3. 更強大的驗證工具:搭配 Joi 或 Yup 在 Express 中檢查 request body。

小結

今天我們完成了 Todo API 的資料驗證與 Schema 設計

  • Mongoose Schema 中加入驗證規則
  • 捕捉 ValidationError 並回應友善的錯誤訊息
  • 測試了正確與錯誤的請求案例
    到這裡,我們的 Todo API 已經有了:
  • CRUD 功能(Day 17)
  • 資料庫支持(Day 18)
  • 完整的資料驗證(Day 19)

上一篇
Day 18: 使用資料庫的 API(以 MongoDB 為例)
下一篇
Day 20:Middleware 介紹與應用
系列文
API 全攻略24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言