12 KiB
12 KiB
OCDP 命名约定对照表
快速参考
| 层级 | 变量/属性 | 类型名 | JSON 字段 |
|---|---|---|---|
| Backend Go | 导出: PascalCase不导出: camelCase |
PascalCase |
snake_case |
| OpenAPI Schema | snake_case |
PascalCase |
snake_case |
| Frontend Generated | snake_case (引号) |
PascalCase |
snake_case |
| Frontend Internal | camelCase |
PascalCase |
snake_case |
详细说明
1. Backend (Go)
// 文件: backend/internal/adapter/input/http/dto/cluster_dto.go
type ClusterResponse struct {
ID string `json:"id"` // 导出字段: PascalCase, JSON: snake_case
Name string `json:"name"`
HasCAData bool `json:"has_ca_data"` // Go: PascalCase → JSON: snake_case
CreatedAt string `json:"created_at"`
}
// 内部变量
func example() {
var clusterId string // 不导出: camelCase
var clusterName string
}
规则:
- ✅ 导出变量/字段:
PascalCase(首字母大写) - ✅ 不导出变量/字段:
camelCase(首字母小写) - ✅ 类型名:
PascalCase - ✅ JSON 标签:
snake_case
2. OpenAPI 规范 (openapi.yaml)
# 文件: backend/docs/openapi.yaml
components:
schemas:
ClusterResponse: # Schema 名称: PascalCase
type: object
properties:
id: # 属性: snake_case
type: string
name:
type: string
has_ca_data: # 属性: snake_case (与 Go JSON 标签一致)
type: boolean
created_at: # 属性: snake_case
type: string
规则:
- ✅ 固定字段 (operationId, paths, etc.):
camelCase - ✅ Schema 本身:
PascalCase - ✅ Schema 下面的属性:
snake_case
3. Frontend TypeScript - 生成的 API Client
// 文件: frontend/src/api/generated/models/cluster-response.ts
// 自动生成,不要手动修改
export interface ClusterResponse {
'id'?: string; // 属性: snake_case (加引号)
'name'?: string;
'has_ca_data'?: boolean; // 保持 snake_case,与 JSON 一致
'created_at'?: string;
}
规则:
- ✅ 类型名:
PascalCase - ✅ 属性:
snake_case(带引号) - ⚠️ 不要手动修改生成的文件
4. Frontend TypeScript - 内部类型
// 文件: frontend/src/core/types/index.ts
// 前端内部使用的类型定义
export interface Cluster {
id: string; // 内部变量: camelCase
name: string;
hasCAData?: boolean; // camelCase (前端惯例)
hasCertData?: boolean;
createdAt: string; // camelCase
updatedAt: string;
}
// API 请求类型 (保持与后端一致)
export interface CreateClusterRequest {
name: string;
host: string;
ca_data: string; // JSON 字段: snake_case
cert_data: string; // 与后端 API 保持一致
key_data: string;
}
规则:
- ✅ 内部变量:
camelCase - ✅ 类型名:
PascalCase - ✅ JSON 序列化 (API 通信):
snake_case
数据流转示例
完整的请求-响应流程
┌─────────────────────────────────────────────────────────────┐
│ 1. 前端组件 (camelCase) │
├─────────────────────────────────────────────────────────────┤
│ const cluster = { │
│ name: "Production", │
│ hasCAData: true, // camelCase │
│ createdAt: "2025-11-10" │
│ } │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 2. API Request Body (snake_case JSON) │
├─────────────────────────────────────────────────────────────┤
│ { │
│ "name": "Production", │
│ "ca_data": "LS0t...", // snake_case │
│ "cert_data": "LS0t..." │
│ } │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 3. Backend Go 结构体 (PascalCase) │
├─────────────────────────────────────────────────────────────┤
│ type CreateClusterRequest struct { │
│ Name string `json:"name"` │
│ CAData string `json:"ca_data"` // Go: PascalCase │
│ CertData string `json:"cert_data"` // JSON: snake_case │
│ } │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 4. API Response JSON (snake_case) │
├─────────────────────────────────────────────────────────────┤
│ { │
│ "id": "cluster-123", │
│ "name": "Production", │
│ "has_ca_data": true, // snake_case │
│ "created_at": "2025-11-10T08:00:00Z" │
│ } │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 5. 前端接收 (可以保持 snake_case 或转换为 camelCase) │
├─────────────────────────────────────────────────────────────┤
│ // 选项 A: 直接使用生成的类型 (snake_case) │
│ const cluster: ClusterResponse = response; │
│ console.log(cluster.has_ca_data); │
│ │
│ // 选项 B: 转换为内部类型 (camelCase) │
│ const cluster: Cluster = { │
│ id: response.id, │
│ hasCAData: response.has_ca_data, // 转换 │
│ createdAt: response.created_at // 转换 │
│ }; │
└─────────────────────────────────────────────────────────────┘
命名转换对照
常见字段名转换
| Go (PascalCase) | JSON (snake_case) | TS Generated | TS Internal (camelCase) |
|---|---|---|---|
ID |
id |
'id' |
id |
Name |
name |
'name' |
name |
ClusterID |
cluster_id |
'cluster_id' |
clusterId |
RegistryID |
registry_id |
'registry_id' |
registryId |
HasCAData |
has_ca_data |
'has_ca_data' |
hasCAData |
CAData |
ca_data |
'ca_data' |
caData |
CertData |
cert_data |
'cert_data' |
certData |
KeyData |
key_data |
'key_data' |
keyData |
CreatedAt |
created_at |
'created_at' |
createdAt |
UpdatedAt |
updated_at |
'updated_at' |
updatedAt |
重新生成 OpenAPI Client
安装依赖
# 安装 Java (如果尚未安装)
sudo apt-get install openjdk-11-jdk
# 安装 OpenAPI Generator CLI (全局)
npm install -g @openapitools/openapi-generator-cli
生成命令
# 方式 1: 使用项目根目录的 Makefile (推荐)
cd /home/mango/workspace/ocdp-go
make openapi-gen-frontend
# 方式 2: 使用前端目录的 npm 脚本
cd /home/mango/workspace/ocdp-go/frontend
npm run openapi-gen
# 方式 3: 直接运行 (如果需要自定义参数)
cd /home/mango/workspace/ocdp-go
openapi-generator-cli generate \
-i backend/docs/openapi.yaml \
-g typescript-axios \
-o frontend/src/api/generated \
--additional-properties=supportsES6=true,withSeparateModelsAndApi=true,apiPackage=api,modelPackage=models
文件权限问题解决
如果遇到权限问题 (文件属于 root):
# 修改生成文件的所有权
sudo chown -R $USER:$USER frontend/src/api/generated
# 然后重新生成
make openapi-gen-frontend
最佳实践
✅ 推荐做法
-
使用生成的类型进行 API 通信
import type { ClusterResponse } from "@/api/generated"; const clusters = await apiRequest<ClusterResponse[]>("/v1/clusters"); -
统一使用 apiRequest helper
import { apiRequest } from "@/shared/utils/api-helpers"; // 自动处理认证、错误、token 刷新 -
后端修改 OpenAPI 后,重新生成前端 client
make openapi-gen-frontend
❌ 避免的做法
-
不要手动修改生成的代码
// ❌ 不要修改 /frontend/src/api/generated/ 下的文件 // 这些文件会在重新生成时被覆盖 -
不要直接使用 fetch
// ❌ 不推荐 const response = await fetch("/api/v1/clusters"); // ✅ 推荐 const clusters = await apiRequest("/v1/clusters"); -
避免混淆命名约定
// ❌ 不要在 API 请求中使用 camelCase const request = { name: "Test", caData: "xxx", // 错误! 应该是 ca_data }; // ✅ 正确 const request = { name: "Test", ca_data: "xxx", // 与后端 JSON 标签一致 };
快速检查清单
Backend (Go)
- 导出字段使用
PascalCase - JSON 标签使用
snake_case - 更新 OpenAPI 规范与代码保持一致
OpenAPI 规范
- Schema 名称使用
PascalCase - 属性使用
snake_case - 与后端 DTO 的 JSON 标签一致
Frontend
- 从 OpenAPI 重新生成 client
- 使用生成的类型进行 API 通信
- 内部类型可以使用
camelCase(可选) - 使用
apiRequesthelper
相关文档
更新日期: 2025-11-10