Automated SDK Generation for Meituan Open Platform
The article details Meituan Open Platform’s approach to automatically generate multi‑language SDKs with rich parameter models, covering overall design, code‑generation via DSL templates, CI/CD integration, and the resulting efficiency gains for third‑party developers integrating over a thousand OpenAPI endpoints.
1. Introduction
Meituan Open Platform provides more than 20 business‑scenario OpenAPIs (e.g., food delivery, group buying, logistics) for third‑party developers. To reduce the high cost of manually coding against complex HTTP contracts, the platform supplies SDKs in multiple programming languages.
2. SDK Goals
The SDK must hide communication protocol details, authentication signatures, timestamp handling, and basic contract logic, while exposing a rich‑parameter model so developers can focus on business logic. The architecture consists of communication‑protocol encapsulation, base‑contract encapsulation, request‑parameter model, and response‑parameter model.
3. Basic SDK Usage Example
Calling the order‑query API with the basic SDK looks like:
MeituanClient client = DefaultMeituanClient.builder(developerId, signKey).build();
// set request parameters
MeituanRequest request = new MeituanRequest("/api/order/queryById");
request.setParam("orderId", "10046789912119");
MeituanResponse response = client.invokeApi(request);
if (response.isSuccess()) {
long price = (long) response.getField("price");
String phone = response.getField("customerPhone");
int orderStatus = (int) response.getField("status");
// business logic
} else {
log.warn("query order failed with response={}", response);
// error handling
}This code still requires developers to manually map each field name and type.
4. Need for Rich Parameter Models
To further simplify development, the SDK adds strongly‑typed request and response classes. Using the same API, the rich‑model code becomes:
MeituanClient client = DefaultMeituanClient.builder(developerId, signKey).build();
// set request parameters
QueryOrderRequest request = new QueryOrderRequest();
request.setOrderId("10046789912119");
MeituanResponse<QueryOrderResponse> response = client.invokeApi(request);
if (response.isSuccess()) {
QueryOrderResponse order = response.getData();
long price = order.getPrice();
String phone = order.getCustomerPhone();
int status = order.getStatus();
log.info("query order finish, price={}, orderStatus={}", price, phone, status);
} else {
log.warn("query order failed with response={}", response);
}Each field’s name, type, and validation rule are generated automatically, dramatically reducing error‑prone manual mapping.
5. Cost Model for Manual SDK Development
The article presents a cost formula (illustrated in the following image) showing that development effort grows linearly with the number of supported APIs and programming languages, making pure manual coding infeasible at scale.
6. Overall Design of the Auto‑Generation System
The system must provide four core capabilities:
Communication‑protocol encapsulation.
Base‑contract encapsulation (timestamp, signature, error codes).
Request‑parameter model generation.
Response‑parameter model generation.
These components are stable and need to be implemented only once per language.
7. Choosing a Code‑Generation Technique
The team evaluated four mainstream approaches:
Template‑based generation (e.g., MVC scaffolding, Vue CLI).
Visual UI generation tools (e.g., Eclipse visual editor, low‑code platforms).
Code‑corpus generation using DSLs or IDL (e.g., Telosys for RPC clients).
AI‑driven generation (e.g., Sketch2Code, teleporthq).
Because SDK code follows strict patterns, the DSL‑based code‑corpus approach was selected.
8. DSL Template for Java SDK
The DSL describes class metadata, static fields, private fields, getters, setters, and annotations. Angle brackets are escaped to keep the template syntactically valid inside the code block.
<@class className=className metaInfo=javaApiMeta baseClass=baseClass interfaces=interfaces classDesc=classDesc package=packageName importPackages=importPackages>
<#if staticFields?? && (staticFields?size > 0)>
<#list staticFields as param>
<@staticField param=param/>
</#list>
</#if>
<#if privateFields?? && (privateFields?size > 0)>
<#list privateFields as param>
<@field param=param/>
</#list>
</#if>
<#if privateFields?? && (privateFields?size > 0)>
<#list privateFields as param>
<@getterMethod param=param/>
<@setterMethod param=param/>
</#list>
</#if>
<#if javaApiMeta?has_content>
<@deserializeResponse metaInfo=javaApiMeta/>
<@serializeToJson metaInfo=javaApiMeta/>
</#if>
<#if privateFields?? && (privateFields?size > 0)>
<@toString className=className params=privateFields/>
</#if>
</@class>9. Generation Process
The pipeline parses API metadata (method, path, request/response fields, example values) and feeds it into the DSL template. For each target language a language‑specific conversion engine replaces DSL macros with concrete Java, C#, Python, etc., code.
Example of the API metadata for the "order_query_by_id" endpoint (excerpt):
APIGroup: waimai
APISubGroup: order
APIName: order_query_by_id
HTTP METHOD: POST
HTTP PATH: /api/order/queryById
Description: 按订单id查询订单详情
Request:
|- orderId LONG NOT_NULL 要查询的订单的id example:1000224201796844308
Response:
|- orderId LONG NOT_NULL 订单id example:1000224201796844308
|- price LONG NOT_NULL 订单金额(单位为人民币“分”) example:3308
|- phone STRING 顾客联系电话 example:"13000000002"
|- products ARRAY<Product> 订单商品列表
|- pid LONG 商品id example:"13000000002"
|- name String 商品名 example:"珍珠奶茶"
|- num INTEGER 商品数量 example:1
|- price LONG 商品单价 example:1199
|- properties ARRAY<Property> 商品属性列表
|- name STRING 商品属性名 example:"甜度"
|- value STRING 商品属性值 example:"七分糖"
|- remark STRING 商品备注 example:"请做常温的"
|- status INTEGER 订单状态 example:710. Generated Java Request/Response Classes
After DSL processing, the engine produces fully‑qualified Java classes with fields, getters, setters, and JSON (de)serialization annotations. The same process applies to other languages by providing a language‑specific DSL template.
11. Generating Example Code
Example‑code generation uses the same metadata to fill field values with the provided example values. The DSL template for example code looks like:
<#setting number_format="computer">
MeituanClient meituanClient = DefaultMeituanClient.builder(10000L, "xxxxx").build();
<#assign reqVarName = className?uncap_first/>
${className} ${reqVarName} = new ${className}();
<#if privateFields?? && (privateFields?size > 0)>
<#list privateFields as field>
${reqVarName}.set${field.fieldName?cap_first}(${field.exampleValue!""});
</#list>
</#if>
<#if javaApiMeta.needAuth>
String appAuthToken = "xxxx";
MeituanResponse<${javaApiMeta.responseClass}> response = meituanClient.invokeApi(request, appAuthToken);
<#else>
MeituanResponse<${javaApiMeta.responseClass}> response = meituanClient.invokeApi(request);
</#if>
if (response.isSuccess()) {
<#if javaApiMeta.responseClass == "Void">
System.out.println("调用成功");
<#else>
${javaApiMeta.responseClass} resp = response.getData();
System.out.println(resp);
</#if>
} else {
System.out.println("调用失败");
}The resulting concrete Java example for the order‑query API is:
MeituanClient client = DefaultMeituanClient.builder(developerId, signKey).build();
// 设置请求参数
OrderQueryByIdRequest request = new OrderQueryByIdRequest();
request.setOrderId(1000224201796844308L);
// 调用接口
MeituanResponse<OrderQueryByIdResponse> response = client.invokeApi(request);
// 处理接口返回
if (response.isSuccess()) {
OrderQueryByIdResponse orderResponse = response.getData();
System.out.println(orderResponse);
} else {
System.out.println("调用失败");
}12. Continuous Integration and Continuous Delivery
After the code‑generation step, a CI/CD pipeline automatically builds, tests, and publishes the SDK. The pipeline monitors API‑metadata changes via binlog and SDK‑logic changes via Git hooks. When a change is detected, the pipeline:
Fetches manually written SDK base code and runs static analysis.
Pulls the latest API metadata and generates rich‑parameter code.
Compiles the combined code, runs unit and end‑to‑end tests, and packages the SDK.
Uploads the artifact, creates a download link, and updates the version information on the official site.
13. Results and Outlook
By automating SDK generation, build, test, and release, Meituan reduced the SDK update cycle from weeks to minutes, lowered developer support tickets, and achieved the original goal of improving integration efficiency with minimal human effort. Future work includes adding more programming‑language templates and further enriching the generated example code.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Meituan Technology Team
Over 10,000 engineers powering China’s leading lifestyle services e‑commerce platform. Supporting hundreds of millions of consumers, millions of merchants across 2,000+ industries. This is the public channel for the tech teams behind Meituan, Dianping, Meituan Waimai, Meituan Select, and related services.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
