如何从SwaggerParseResult还原原始JSON并实现深拷贝?
问题:OpenAPIV3Parser无法序列化SwaggerParseResult,导致深拷贝失败
我发现OpenAPIV3Parser只提供反序列化OpenAPI文档JSON的方法,没法把SwaggerParseResult序列化回JSON。比如我要对SwaggerParseResult做深拷贝,尝试把它序列化回JSON再反序列化生成新实例,但这么做得到的新SwaggerParseResult调用getOpenAPI()会返回null,没法被Swagger UI正常识别。现在需要找到可行的解决办法,前提是不能在内存里存原始JSON,且重新序列化后的JSON必须是有效的OpenAPI文档。
尝试的代码
package com.example.dynamicgateway.parser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.parser.OpenAPIV3Parser; import io.swagger.v3.parser.core.models.SwaggerParseResult; import org.junit.jupiter.api.Test; public class ParserTest { private final OpenAPIV3Parser parser = new OpenAPIV3Parser(); @Test void testParser() throws JsonProcessingException { String testDoc = getTestDoc(); SwaggerParseResult parseResult = parser.readContents(testDoc); // 试过带不带writerWithDefaultPrettyPrinter()都不行 String reserializedDoc = new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(parseResult); // 反序列化后OpenApi为null SwaggerParseResult redeserializedDoc = parser.readContents(reserializedDoc); } String getTestDoc() { return """ { "openapi": "3.0.1", "info": { "title": "Hello World API", "version": "1.0" }, "servers": [ { "url": "http://localhost:8090", "description": "Generated server url" } ], "paths": { "/joy": { "get": { "tags": [ "Message Controller" ], "operationId": "getMessageOfJoy", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/SuccessMessage" } } } } } } }, "/auth/hello-world": { "get": { "tags": [ "Message Controller" ], "operationId": "getHelloWorld", "parameters": [ { "name": "principal", "in": "query", "required": false, "schema": { "type": "string" } } ], "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/SuccessMessage" } } } } } } }, "/error": { "get": { "tags": [ "my-error-controller" ], "operationId": "error", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/FailureMessage" } } } } } }, "put": { "tags": [ "my-error-controller" ], "operationId": "error_3", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/FailureMessage" } } } } } }, "post": { "tags": [ "my-error-controller" ], "operationId": "error_2", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/FailureMessage" } } } } } }, "delete": { "tags": [ "my-error-controller" ], "operationId": "error_5", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/FailureMessage" } } } } } }, "options": { "tags": [ "my-error-controller" ], "operationId": "error_6", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/FailureMessage" } } } } } }, "head": { "tags": [ "my-error-controller" ], "operationId": "error_1", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/FailureMessage" } } } } } }, "patch": { "tags": [ "my-error-controller" ], "operationId": "error_4", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/FailureMessage" } } } } } } } }, "components": { "schemas": { "SuccessMessage": { "type": "object", "properties": { "message": { "type": "string" } } }, "FailureMessage": { "type": "object", "properties": { "message": { "type": "string" }, "method": { "type": "string", "enum": [ "GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "TRACE" ] }, "request_path": { "type": "string" } } } } } } """; } }
解决办法
问题出在直接序列化SwaggerParseResult上——这个类是解析过程的包装容器,包含解析元数据(错误、警告)和最终的OpenAPI对象,它本身不是为序列化设计的,直接用Jackson序列化会生成不符合OpenAPI规范的JSON,自然无法被OpenAPIV3Parser正确反序列化。
正确的处理流程:
- 从
SwaggerParseResult中取出核心的OpenAPI对象 - 使用Swagger官方提供的序列化工具,将
OpenAPI对象序列化为符合规范的JSON - 再用
OpenAPIV3Parser反序列化该JSON,得到有效的SwaggerParseResult
具体实现
首先确保引入Swagger核心依赖(版本与你的parser保持一致):
<dependency> <groupId>io.swagger.core.v3</groupId> <artifactId>swagger-core</artifactId> <version>2.2.15</version> </dependency>
修改后的测试代码:
package com.example.dynamicgateway.parser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.util.Json; import io.swagger.v3.parser.OpenAPIV3Parser; import io.swagger.v3.parser.core.models.SwaggerParseResult; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertNotNull; public class ParserTest { private final OpenAPIV3Parser parser = new OpenAPIV3Parser(); // 使用Swagger官方配置好的ObjectMapper,保证序列化符合OpenAPI规范 private final ObjectMapper openApiMapper = Json.mapper(); @Test void testParser() throws JsonProcessingException { String testDoc = getTestDoc(); SwaggerParseResult parseResult = parser.readContents(testDoc); // 确认初始解析得到的OpenAPI非空 assertNotNull(parseResult.getOpenAPI()); // 序列化核心的OpenAPI对象,而非SwaggerParseResult String reserializedDoc = openApiMapper.writerWithDefaultPrettyPrinter() .writeValueAsString(parseResult.getOpenAPI()); // 反序列化JSON得到新的SwaggerParseResult SwaggerParseResult redeserializedDoc = parser.readContents(reserializedDoc); // 验证新实例的OpenAPI非空且有效 assertNotNull(redeserializedDoc.getOpenAPI()); } String getTestDoc() { return """ { "openapi": "3.0.1", "info": { "title": "Hello World API", "version": "1.0" }, "servers": [ { "url": "http://localhost:8090", "description": "Generated server url" } ], "paths": { "/joy": { "get": { "tags": [ "Message Controller" ], "operationId": "getMessageOfJoy", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/SuccessMessage" } } } } } } }, "/auth/hello-world": { "get": { "tags": [ "Message Controller" ], "operationId": "getHelloWorld", "parameters": [ { "name": "principal", "in": "query", "required": false, "schema": { "type": "string" } } ], "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/SuccessMessage" } } } } } } }, "/error": { "get": { "tags": [ "my-error-controller" ], "operationId": "error", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/FailureMessage" } } } } } }, "put": { "tags": [ "my-error-controller" ], "operationId": "error_3", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/FailureMessage" } } } } } }, "post": { "tags": [ "my-error-controller" ], "operationId": "error_2", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/FailureMessage" } } } } } }, "delete": { "tags": [ "my-error-controller" ], "operationId": "error_5", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/FailureMessage" } } } } } }, "options": { "tags": [ "my-error-controller" ], "operationId": "error_6", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/FailureMessage" } } } } } }, "head": { "tags": [ "my-error-controller" ], "operationId": "error_1", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/FailureMessage" } } } } } }, "patch": { "tags": [ "my-error-controller" ], "operationId": "error_4", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/FailureMessage" } } } } } } } }, "components": { "schemas": { "SuccessMessage": { "type": "object", "properties": { "message": { "type": "string" } } }, "FailureMessage": { "type": "object", "properties": { "message": { "type": "string" }, "method": { "type": "string", "enum": [ "GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "TRACE" ] }, "request_path": { "type": "string" } } } } } } """; } }
关键说明
Json.mapper()是Swagger官方提供的ObjectMapper,已经预配置了OpenAPI对象的序列化规则,能生成完全符合规范的JSON文档- 不要直接操作
SwaggerParseResult的序列化,它只是解析过程的结果容器,核心的API定义都在OpenAPI对象中 - 如果需要完整拷贝
SwaggerParseResult,可以在反序列化得到新的OpenAPI后,手动构建新的SwaggerParseResult实例并设置相关属性
内容的提问来源于stack exchange,提问作者Sergey Zolotarev
相关产品推荐
相关产品推荐

