如何让openapi-generator-maven-plugin将请求头对象序列化为JSON
问题描述
我尝试使用openapi-generator-maven-plugin的Java生成器,将复杂对象序列化为JSON而非调用toString()方法,但生成的Java客户端无法实现请求头对象的JSON序列化效果。
相关代码与配置
自定义DTO类
@Data public class RequestContextDTO { @Valid private TrackingDTO tracking; } @Data public class TrackingDTO { private String trackingNumber; }
OpenAPI YAML定义
openapi: 3.0.1 info: title: Test Header Serialization version: "1" servers: - url: http://localhost:8080 description: Generated server url paths: /test/: get: tags: - MyController summary: Test Header As Complex Object operationId: postRequestWithHeader parameters: - name: x-request-context in: header description: Request context required: true content: application/json: schema: $ref: "#/components/schemas/RequestContextDTO" responses: "200": description: Success components: schemas: RequestContextDTO: required: - businessContext - userInfo type: object properties: tracking: $ref: "#/components/schemas/TrackingDTO" TrackingDTO: required: - trackingNumber type: object properties: trackingNumber: type: string
Maven插件配置
<plugin> <groupId>org.openapitools</groupId> <artifactId>openapi-generator-maven-plugin</artifactId> <version>7.8.0</version> <executions> <execution> <goals> <goal>generate</goal> </goals> <configuration> <inputSpec>/definitions/newApi.yaml</inputSpec> <generatorName>java</generatorName> <generateApiDocumentation>false</generateApiDocumentation> <configOptions> <library>jersey3</library> <useJakartaEe>true</useJakartaEe> <dateLibrary>java8</dateLibrary> <apiPackage>${client.package}.api</apiPackage> <invokerPackage>${client.package}.api</invokerPackage> <modelPackage>${client.package}.model</modelPackage> <performBeanValidation>false</performBeanValidation> <serializationLibrary>jackson</serializationLibrary> </configOptions> </configuration> </execution> </executions> </plugin>
生成的问题代码
MyControllerApi生成代码
public class MyControllerApi { private ApiClient apiClient; public ApiResponse<Void> postRequestWithHeaderWithHttpInfo(RequestContextDTO xRequestContext) throws ApiException { if (xRequestContext == null) { throw new ApiException(400, "Missing the required parameter 'xRequestContext' when calling postRequestWithHeader"); } else { Map<String, String> localVarHeaderParams = new LinkedHashMap(); localVarHeaderParams.put("x-request-context", this.apiClient.parameterToString(xRequestContext)); String localVarAccept = this.apiClient.selectHeaderAccept(new String[0]); String localVarContentType = this.apiClient.selectHeaderContentType(new String[0]); return this.apiClient.invokeAPI("MyControllerApi.postRequestWithHeader", "/test/", "GET", new ArrayList(), (Object)null, localVarHeaderParams, new LinkedHashMap(), new LinkedHashMap(), localVarAccept, localVarContentType, (String[])null, (GenericType)null, false); } } }
ApiClient的parameterToString方法
public String parameterToString(Object param) { if (param == null) { return ""; } else if (param instanceof Date) { return formatDate((Date) param); } else if (param instanceof OffsetDateTime) { return formatOffsetDateTime((OffsetDateTime) param); } else if (param instanceof Collection<?>) { StringBuilder b = new StringBuilder(); for(Object o : (Collection<?>)param) { if(b.length() > 0) { b.append(','); } b.append(String.valueOf(o)); } return b.toString(); } else { return String.valueOf(param); } }
当前生成的代码会调用RequestContextDTO的toString()方法而非序列化为JSON,请问能否通过插件配置或调整YAML实现请求头复杂对象的JSON序列化?
解决方案
可以通过以下几种方式实现需求:
1. 自定义ApiClient模板,修改参数序列化逻辑
openapi-generator支持通过Freemarker模板自定义生成逻辑:
- 从openapi-generator源码中获取Java生成器的
ApiClient.mustache模板 - 修改
parameterToString方法,增加复杂对象的JSON序列化分支:public String parameterToString(Object param) { if (param == null) { return ""; } else if (param instanceof Date) { return formatDate((Date) param); } else if (param instanceof OffsetDateTime) { return formatOffsetDateTime((OffsetDateTime) param); } else if (param instanceof Collection<?>) { StringBuilder b = new StringBuilder(); for(Object o : (Collection<?>)param) { if(b.length() > 0) { b.append(','); } b.append(parameterToString(o)); } return b.toString(); } else if (!isSimpleType(param.getClass())) { // 利用Jackson序列化复杂对象为JSON try { return getObjectMapper().writeValueAsString(param); } catch (JsonProcessingException e) { throw new RuntimeException("Failed to serialize parameter to JSON", e); } } else { return String.valueOf(param); } } // 辅助方法判断是否为简单类型 private boolean isSimpleType(Class<?> clazz) { return clazz.isPrimitive() || clazz.equals(String.class) || clazz.equals(Integer.class) || clazz.equals(Long.class) || clazz.equals(Double.class) || clazz.equals(Boolean.class) || clazz.equals(Float.class) || clazz.equals(Short.class) || clazz.equals(Byte.class); } - 在Maven插件配置中添加自定义模板目录:
<configuration> <!-- 其他原有配置 --> <templateDirectory>${project.basedir}/src/main/resources/openapi-templates</templateDirectory> </configuration>
2. 调整OpenAPI YAML(辅助优化)
虽然OpenAPI 3.0支持头参数的content/application/json定义,但部分生成器对该场景支持有限,可尝试在schema中添加format: json标记:
parameters: - name: x-request-context in: header required: true content: application/json: schema: $ref: "#/components/schemas/RequestContextDTO" format: json
该方式需结合模板修改使用,单独使用不一定生效。
3. 生成后手动扩展(临时方案)
若不想修改模板,可在生成代码后手动扩展ApiClient的parameterToString方法,或在调用API前自行序列化对象:
// 调用前手动序列化 RequestContextDTO context = new RequestContextDTO(); // 设置属性 String jsonContext = new ObjectMapper().writeValueAsString(context); // 注意需修改API方法参数为String类型,或自行适配 myControllerApi.postRequestWithHeaderWithHttpInfo(jsonContext);
此方式需修改API调用代码,仅作为临时替代方案。
内容的提问来源于stack exchange,提问作者BlaZz91
相关产品推荐
相关产品推荐

