Skip to content

API 响应格式规范

核心原则

API 响应必须使用统一的格式,遵循 Ant Design Pro 响应规范,确保前后端数据交互的一致性。

允许的做法

成功响应(单条数据)

  • 使用 success: true 表示成功
  • 使用 data 字段包含响应数据
json
{
  "success": true,
  "data": {
    "id": 123,
    "name": "Alice",
    "email": "alice@example.com",
    "createdAt": 1704038400
  }
}
go
// ✅ 正确 - Go 实现
type BaseResponse struct {
    Success bool        `json:"success"`
    Data    interface{} `json:"data,omitempty"`
}

func Success(data interface{}) BaseResponse {
    return BaseResponse{
        Success: true,
        Data:    data,
    }
}

// Handler 中使用
func GetUser(c echo.Context) error {
    user, _ := userService.GetByID(id)
    return c.JSON(http.StatusOK, response.Success(user))
}

成功响应(列表数据/分页)

  • 使用 success: true
  • 使用 data 数组包含列表数据
  • 使用 totalcurrentpageSize 表示分页信息
json
{
  "success": true,
  "data": [
    { "id": 1, "name": "Alice" },
    { "id": 2, "name": "Bob" }
  ],
  "total": 100,
  "current": 1,
  "pageSize": 20
}
go
// ✅ 正确 - Go 实现
type PagedResponse struct {
    Success  bool        `json:"success"`
    Data     interface{} `json:"data,omitempty"`
    Total    int64       `json:"total,omitempty"`
    Current  int         `json:"current,omitempty"`
    PageSize int         `json:"pageSize,omitempty"`
}

func SuccessPaged(data interface{}, total int64, current, pageSize int) PagedResponse {
    return PagedResponse{
        Success:  true,
        Data:     data,
        Total:    total,
        Current:  current,
        PageSize: pageSize,
    }
}

// Handler 中使用
func ListUsers(c echo.Context) error {
    users, total, _ := userService.List(page, pageSize)
    return c.JSON(http.StatusOK, response.SuccessPaged(users, total, page, pageSize))
}

失败响应

  • 使用 success: false
  • 使用 errorMessage 说明错误原因
  • 使用 errorCode 标识错误类型
json
{
  "success": false,
  "errorMessage": "用户不存在",
  "errorCode": 1002
}
go
// ✅ 正确 - Go 实现
type ErrorResponse struct {
    Success      bool   `json:"success"`
    ErrorMessage string `json:"errorMessage,omitempty"`
    ErrorCode    int    `json:"errorCode,omitempty"`
}

func Fail(errorCode int, errorMessage string) ErrorResponse {
    return ErrorResponse{
        Success:      false,
        ErrorMessage: errorMessage,
        ErrorCode:    errorCode,
    }
}

// Handler 中使用
func GetUser(c echo.Context) error {
    user, err := userService.GetByID(id)
    if err != nil {
        return c.JSON(http.StatusNotFound, response.Fail(1002, "用户不存在"))
    }
    return c.JSON(http.StatusOK, response.Success(user))
}

字段校验错误响应

字段校验失败时,返回详细的字段错误信息:

json
{
  "success": false,
  "errorMessage": "参数校验失败",
  "errorCode": 1001,
  "errors": [
    { "field": "email", "message": "邮箱格式不正确" },
    { "field": "password", "message": "密码长度至少8位" }
  ]
}
go
// ✅ 正确 - 字段校验错误响应
type ValidationErrorResponse struct {
    Success      bool             `json:"success"`
    ErrorMessage string           `json:"errorMessage,omitempty"`
    ErrorCode    int              `json:"errorCode,omitempty"`
    Errors       []ValidationError `json:"errors,omitempty"`
}

type ValidationError struct {
    Field   string `json:"field"`
    Message string `json:"message"`
}

func FailWithValidation(errorCode int, errorMessage string, errors []ValidationError) ValidationErrorResponse {
    return ValidationErrorResponse{
        Success:      false,
        ErrorMessage: errorMessage,
        ErrorCode:    errorCode,
        Errors:       errors,
    }
}

// Handler 中使用
func (h *UserHandler) Create(c echo.Context) error {
    var req CreateUserRequest
    if err := c.Bind(&req); err != nil {
        return c.JSON(400, response.Fail(1000, "参数格式错误"))
    }

    if err := c.Validate(&req); err != nil {
        return c.JSON(400, response.FailWithValidation(1001, "参数校验失败", []response.ValidationError{
            {Field: "email", Message: "邮箱格式不正确"},
            {Field: "password", Message: "密码长度至少8位"},
        }))
    }

    // 创建用户逻辑...
}

删除操作响应

  • 使用 success: true
  • 可选 返回空 data 或不返回 data
json
{
  "success": true
}
go
// ✅ 正确 - Go 实现
func DeleteUser(c echo.Context) error {
    err := userService.Delete(id)
    if err != nil {
        return c.JSON(http.StatusInternalServerError, response.Fail(500, "删除失败"))
    }
    return c.JSON(http.StatusOK, response.Success(nil))
}

禁止的做法

禁止的响应格式

  • 禁止 直接返回数据(不包装)
  • 禁止 返回不一致的结构
  • 禁止 在成功响应中包含 error 字段
json
❌ 错误 - 直接返回数据
{
  "id": 123,
  "name": "Alice"
}

❌ 错误 - 不一致的结构
{
  "code": 200,
  "message": "success",
  "result": {...}
}

❌ 错误 - 成功响应包含 error
{
  "success": true,
  "data": {...},
  "error": null
}

完整响应示例

创建资源

POST /api/v1/users
Request:
{
  "name": "Alice",
  "email": "alice@example.com"
}

Response (201 Created):
{
  "success": true,
  "data": {
    "id": 123,
    "name": "Alice",
    "email": "alice@example.com",
    "createdAt": 1704038400
  }
}

更新资源

PATCH /api/v1/users/123
Request:
{
  "name": "Alice Wang"
}

Response (200 OK):
{
  "success": true,
  "data": {
    "id": 123,
    "name": "Alice Wang",
    "email": "alice@example.com",
    "updatedAt": 1704038500
  }
}

获取列表(分页)

GET /api/v1/users?page=1&pageSize=20

Response (200 OK):
{
  "success": true,
  "data": [
    { "id": 1, "name": "Alice", "email": "alice@example.com" },
    { "id": 2, "name": "Bob", "email": "bob@example.com" }
  ],
  "total": 100,
  "current": 1,
  "pageSize": 20
}

参数验证错误

POST /api/v1/users
Request:
{
  "name": "",
  "email": "invalid-email"
}

Response (400 Bad Request):
{
  "success": false,
  "errorMessage": "参数验证失败:邮箱格式不正确",
  "errorCode": 1000
}

资源不存在

GET /api/v1/users/999

Response (404 Not Found):
{
  "success": false,
  "errorMessage": "用户不存在",
  "errorCode": 1001
}

服务器错误

GET /api/v1/users

Response (500 Internal Server Error):
{
  "success": false,
  "errorMessage": "服务器内部错误",
  "errorCode": 500
}

特殊场景

批量操作响应

json
{
  "success": true,
  "data": {
    "successCount": 8,
    "failCount": 2,
    "failed": [
      { "id": 3, "reason": "用户不存在" },
      { "id": 7, "reason": "无权限删除" }
    ]
  }
}

文件上传响应

json
{
  "success": true,
  "data": {
    "url": "https://cdn.example.com/files/abc123.jpg",
    "filename": "avatar.jpg",
    "size": 102400
  }
}

TypeScript 类型定义

响应类型

typescript
// ✅ 正确 - TypeScript 类型定义
export interface BaseResponse<T = any> {
  success: boolean;
  data?: T;
}

export interface ErrorResponse {
  success: false;
  errorMessage: string;
  errorCode: number;
}

export interface ValidationErrorResponse extends ErrorResponse {
  errors?: Array<{
    field: string;
    message: string;
  }>;
}

export interface PagedResponse<T = any> {
  success: boolean;
  data?: T[];
  total?: number;
  current?: number;
  pageSize?: number;
}

// 联合类型:响应可能成功或失败
export type APIResponse<T = any> = BaseResponse<T> | ErrorResponse | ValidationErrorResponse;

前端使用示例

typescript
// ✅ 正确 - 前端请求处理
import { message } from 'antd';
import type { BaseResponse, ErrorResponse } from '@/types/response';

// 示例 1:获取单条数据
async function getUser(id: number) {
  const response = await request.get<BaseResponse<User>>(`/api/v1/users/${id}`);

  if (!response.success) {
    message.error(response.errorMessage || '请求失败');
    return null;
  }

  return response.data;
}

// 示例 2:获取列表数据(分页)
async function getUserList(params: { current: number; pageSize: number }) {
  const response = await request.get<PagedResponse<User>>('/api/v1/users', { params });

  if (!response.success) {
    message.error(response.errorMessage || '获取列表失败');
    return { data: [], total: 0 };
  }

  return {
    data: response.data || [],
    total: response.total || 0,
  };
}

// 示例 3:创建资源
async function createUser(data: CreateUserParams) {
  const response = await request.post<BaseResponse<User>>('/api/v1/users', data);

  if (!response.success) {
    if ('errors' in response && response.errors) {
      // 处理字段校验错误
      response.errors.forEach(err => {
        message.error(`${err.field}: ${err.message}`);
      });
    } else {
      message.error(response.errorMessage || '创建失败');
    }
    return null;
  }

  message.success('创建成功');
  return response.data;
}

// 示例 4:使用 ProTable
import type { ProColumns } from '@ant-design/pro-components';
import { ProTable } from '@ant-design/pro-components';

const columns: ProColumns<User>[] = [
  { title: 'ID', dataIndex: 'id' },
  { title: '姓名', dataIndex: 'name' },
  { title: '邮箱', dataIndex: 'email' },
];

<ProTable<User>
  columns={columns}
  request={async (params) => {
    const response = await request.get<PagedResponse<User>>('/api/v1/users', {
      params: {
        current: params.current,
        pageSize: params.pageSize,
        ...params,
      },
    });

    return {
      data: response.data || [],
      success: response.success,
      total: response.total || 0,
    };
  }}
/>

统一请求拦截器

typescript
// ✅ 正确 - 请求拦截器处理响应
import axios from 'axios';
import { message } from 'antd';

const request = axios.create({
  baseURL: '/api/v1',
  timeout: 10000,
});

// 响应拦截器
request.interceptors.response.use(
  (response) => {
    const data = response.data;

    // 检查响应是否成功
    if (data.success === false) {
      // 处理字段校验错误
      if (data.errors && Array.isArray(data.errors)) {
        data.errors.forEach((err: any) => {
          message.error(`${err.field}: ${err.message}`);
        });
      } else {
        message.error(data.errorMessage || '请求失败');
      }

      return Promise.reject(data);
    }

    return data;
  },
  (error) => {
    message.error('网络错误,请稍后重试');
    return Promise.reject(error);
  }
);

export default request;

Go 实现完整示例

go
// backend/httpapi/response/response.go
package response

// BaseResponse 基础响应
type BaseResponse struct {
    Success bool        `json:"success"`
    Data    interface{} `json:"data,omitempty"`
}

// ErrorResponse 错误响应
type ErrorResponse struct {
    Success      bool   `json:"success"`
    ErrorMessage string `json:"errorMessage,omitempty"`
    ErrorCode    int    `json:"errorCode,omitempty"`
}

// PagedResponse 分页响应
type PagedResponse struct {
    Success  bool        `json:"success"`
    Data     interface{} `json:"data,omitempty"`
    Total    int64       `json:"total,omitempty"`
    Current  int         `json:"current,omitempty"`
    PageSize int         `json:"pageSize,omitempty"`
}

// Success 创建成功响应
func Success(data interface{}) BaseResponse {
    return BaseResponse{Success: true, Data: data}
}

// Fail 创建失败响应
func Fail(errorCode int, errorMessage string) ErrorResponse {
    return ErrorResponse{
        Success:      false,
        ErrorMessage: errorMessage,
        ErrorCode:    errorCode,
    }
}

// SuccessPaged 创建分页成功响应
func SuccessPaged(data interface{}, total int64, current, pageSize int) PagedResponse {
    return PagedResponse{
        Success:  true,
        Data:     data,
        Total:    total,
        Current:  current,
        PageSize: pageSize,
    }
}

相关文档