生成支持多内容类型、自定义序列化与鉴别器的OpenAPI TS客户端
解决方案:用OpenAPI Generator定制TypeScript客户端支持BCS与鉴别器
核心思路
选OpenAPI Generator的typescript-fetch生成器,它支持自定义模板和扩展点,能覆盖多Content-Type、鉴别器解析、BCS序列化注入的全部需求。
步骤1:基础客户端生成
先生成带鉴别器支持的基础TS客户端,执行以下命令:
openapi-generator generate \ -i your-api-spec.yaml \ -g typescript-fetch \ -o ./generated-client \ --additional-properties=discriminatorUsePolymorphism=true,typescriptThreePlus=true
discriminatorUsePolymorphism=true:启用多态类型生成,自动处理oneOf/allOf结构的鉴别器逻辑typescriptThreePlus=true:生成符合TS3+语法的代码
步骤2:扩展BCS序列化/反序列化能力
1. 编写BCS工具类
在生成的客户端目录下创建bcs-utils.ts,封装BCS处理逻辑:
// 替换为你实际使用的BCS库 import { BCS } from '@mysten/bcs'; export const bcs = new BCS({ encoding: 'base64' }); // 注册OpenAPI中定义的所有Schema类型 bcs.registerStructType('GenesisTransaction', { /* 匹配你的类型结构 */ }); bcs.registerStructType('UserTransaction', { /* 匹配你的类型结构 */ }); bcs.registerStructType('SubmitTransactionRequest', { /* 匹配你的类型结构 */ }); // ... 其他需要处理的类型 export function serializeToBCS<T>(data: T, typeName: string): Uint8Array { return bcs.serialize(typeName, data); } export function deserializeFromBCS<T>(bytes: Uint8Array, typeName: string): T { return bcs.deserialize(typeName, bytes); }
2. 修改核心请求类,注入格式自动切换逻辑
找到生成的ApiClient.ts(或类似核心请求文件),修改request方法,根据请求头自动处理序列化/反序列化:
async request<T>(context: RequestContext): Promise<T> { let body: any = context.body; // 处理请求序列化:根据Content-Type选择格式 if (context.headers['Content-Type'] === 'application/x-bcs') { // 根据API路径、方法映射对应的Schema类型名,可手动维护或通过模板自动生成 const typeName = getRequestTypeName(context.path, context.method); body = serializeToBCS(body, typeName); } else { body = JSON.stringify(body); } const response = await fetch(context.url, { method: context.method, headers: context.headers, body, }); // 处理响应反序列化:根据Accept头选择格式 const acceptHeader = context.headers['Accept'] || 'application/json'; let responseData: any; if (acceptHeader === 'application/x-bcs') { const bytes = await response.arrayBuffer(); const typeName = getResponseTypeName(context.path, context.method, response.status); responseData = deserializeFromBCS(new Uint8Array(bytes), typeName); } else { responseData = await response.json(); } // 生成的代码已包含鉴别器类型转换逻辑,直接返回即可 return responseData as T; }
注:getRequestTypeName和getResponseTypeName需根据API路径、方法、状态码映射到对应的Schema名称,可手动维护映射表,或通过自定义模板自动化生成。
3. 自定义模板(可选,自动化类型映射)
若要避免手动维护类型映射,可自定义OpenAPI Generator模板:
- 复制
typescript-fetch官方模板中的api.mustache文件到本地 - 修改模板,在生成API方法时自动注入对应的Schema类型名,生成映射表
- 重新生成时添加
--template-dir=./your-custom-templates参数指定模板目录
步骤3:使用生成的客户端
调用API时只需指定请求头,即可自动切换JSON/BCS格式:
import { TransactionApi, SubmitTransactionRequest } from './generated-client'; const api = new TransactionApi({ basePath: 'https://your-api-server.com' }); // 发送BCS请求,接收BCS响应 const bcsRequest: SubmitTransactionRequest = { /* 请求数据 */ }; const bcsResponse = await api.createTransaction(bcsRequest, { headers: { 'Content-Type': 'application/x-bcs', 'Accept': 'application/x-bcs', }, }); // 发送JSON请求,接收JSON响应 const jsonResponse = await api.createTransaction(bcsRequest, { headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, });
关键特性验证
- 多格式支持:通过
Content-Type和Accept头自动切换序列化/反序列化逻辑 - 鉴别器处理:生成的代码会自动识别
type鉴别字段,完成oneOf/allOf类型的转换 - BCS封装:序列化逻辑完全封装在客户端内部,业务代码无需关心底层实现
内容的提问来源于stack exchange,提问作者Daniel Porteous
相关产品推荐
相关产品推荐

