# Schema 校验（JSON Schema）

URL: https://caijiao.org/fastify/routing/schema-validation
Source: docs/fastify/routing/schema-validation.md
Description: 介绍如何在 Fastify 中使用 JSON Schema 对请求和响应数据进行结构校验与类型约束。

[Fastify](/fastify/) 原生支持 JSON Schema 标准，允许你为请求参数和响应数据定义严格的结构规则，提升接口的健壮性与可维护性。

## 定义请求校验 Schema

你可以通过 `schema` 属性对请求的 `body`、`params`、`querystring` 和 `headers` 进行校验：

```js
fastify.post('/user', {
  schema: {
    body: {
      type: 'object',
      required: ['name', 'email'],
      properties: {
        name: { type: 'string' },
        email: { type: 'string', format: 'email' },
        age: { type: 'integer', minimum: 0 }
      }
    }
  }
}, async (request) => {
  return { status: 'ok' };
});
```

若客户端传入的数据不符合 Schema，Fastify 会自动返回 `400` 错误，并提供详细的错误信息。

## 校验路径参数和查询参数

```js
fastify.get('/items/:id', {
  schema: {
    params: {
      type: 'object',
      properties: {
        id: { type: 'string', pattern: '^[0-9]+$' }
      },
      required: ['id']
    },
    querystring: {
      type: 'object',
      properties: {
        limit: { type: 'integer', minimum: 1, maximum: 100 }
      }
    }
  }
}, async (request) => {
  return { id: request.params.id };
});
```

## 定义响应 Schema

你还可以使用 `response` 字段为不同状态码下的响应定义 Schema：

```js
fastify.get('/profile', {
  schema: {
    response: {
      200: {
        type: 'object',
        properties: {
          username: { type: 'string' },
          email: { type: 'string' }
        }
      }
    }
  }
}, async () => {
  return { username: 'tom', email: 'tom@example.com' };
});
```

如果返回的数据不符合 Schema，开发阶段会抛出异常，有助于快速发现错误。

## 复用 Schema

可通过外部变量或插件的方式复用 Schema：

```js
const userSchema = {
  type: 'object',
  required: ['username'],
  properties: {
    username: { type: 'string' }
  }
};

fastify.post('/login', {
  schema: {
    body: userSchema
  }
}, async (request) => {
  return { success: true };
});
```

## Schema 编译器自定义

Fastify 允许替换默认的 JSON Schema 编译器（如使用 AJV 配置项）：

```js
const fastify = require('fastify')({
  ajv: {
    customOptions: {
      allErrors: true,
      removeAdditional: 'all'
    }
  }
});
```
