From 3c95a3104a4cee58971d34390296075bea06db62 Mon Sep 17 00:00:00 2001 From: gcornacchia Date: Thu, 28 Nov 2024 10:46:14 +0100 Subject: [PATCH] fix generating models for inline arrays --- .../base/BaseJsonSchemaGenerator.java | 26 +- .../impl/DraftV4JsonSchemaGenerator.java | 4 +- .../test/TestGenerationFromOAS3.java | 3 + .../resources/petstoreoas3ArrayInline.json | 273 ++++++++++++++++++ 4 files changed, 297 insertions(+), 9 deletions(-) create mode 100644 src/test/resources/petstoreoas3ArrayInline.json diff --git a/src/main/java/it/imolainformatica/openapi2jsonschema4j/base/BaseJsonSchemaGenerator.java b/src/main/java/it/imolainformatica/openapi2jsonschema4j/base/BaseJsonSchemaGenerator.java index 4be6fc7..1aa66ad 100644 --- a/src/main/java/it/imolainformatica/openapi2jsonschema4j/base/BaseJsonSchemaGenerator.java +++ b/src/main/java/it/imolainformatica/openapi2jsonschema4j/base/BaseJsonSchemaGenerator.java @@ -26,6 +26,8 @@ public class BaseJsonSchemaGenerator { public static final String APPLICATION_JSON = "application/json"; + public static final String REQUEST = "request"; + public static final String RESPONSE = "response"; @Getter protected Map generatedObjects = new HashMap(); protected static final String ORIGINAL_REF = "originalRef"; @@ -77,10 +79,9 @@ private void analyzeOperation(PathItem v) { } else { log.warn("code={} response schema is not a referenced definition! type={}", key, r.getContent().get("application/json").getClass()); log.debug("Reference not found, creating it manually"); - if (!(sc instanceof ArraySchema)) { - objectsDefinitions.put(op.getOperationId()+"response"+key, sc); - messageObjects.add(op.getOperationId()+"response"+key); - } + String inlineObjectKey = createInlineResponseObjectKey(op,key); + objectsDefinitions.put(inlineObjectKey, sc); + messageObjects.add(inlineObjectKey); } } } @@ -88,6 +89,8 @@ private void analyzeOperation(PathItem v) { } } + + private void findRequestBodySchema(Operation op, Set messageObjects) { if (op.getRequestBody()!=null) { if (op.getRequestBody().getContent().get(APPLICATION_JSON)!=null) { @@ -99,10 +102,9 @@ private void findRequestBodySchema(Operation op, Set messageObjects) { } else { log.warn("Request schema is not a referenced definition!"); log.debug("Ref not found, cresting it manually if object"); - if (!(sc instanceof ArraySchema)) { - objectsDefinitions.put(op.getOperationId()+"request", sc); - messageObjects.add(op.getOperationId()+"request"); - } + String inlineObjectKey = createInlineRequestObjectKey(op); + objectsDefinitions.put(inlineObjectKey, sc); + messageObjects.add(inlineObjectKey); } } } else { @@ -110,4 +112,12 @@ private void findRequestBodySchema(Operation op, Set messageObjects) { } } } + + private String createInlineRequestObjectKey(Operation op) { + return op.getOperationId()+ REQUEST; + } + + private String createInlineResponseObjectKey(Operation op, String responseKey) { + return op.getOperationId()+ RESPONSE +responseKey; + } } diff --git a/src/main/java/it/imolainformatica/openapi2jsonschema4j/impl/DraftV4JsonSchemaGenerator.java b/src/main/java/it/imolainformatica/openapi2jsonschema4j/impl/DraftV4JsonSchemaGenerator.java index 1996272..cafd449 100644 --- a/src/main/java/it/imolainformatica/openapi2jsonschema4j/impl/DraftV4JsonSchemaGenerator.java +++ b/src/main/java/it/imolainformatica/openapi2jsonschema4j/impl/DraftV4JsonSchemaGenerator.java @@ -175,7 +175,9 @@ private void navigateModel(String originalRef, List usedDefinition, Map< log.debug("array model={}",res.get(ITEMS)); if (res.get(ITEMS) instanceof Schema) { Schema s = (Schema) res.get(ITEMS); - navigateModel(s.get$ref(),usedDefinition,res,null); + if (s.get$ref()!=null) { + navigateModel(s.get$ref(), usedDefinition, res, null); + } } } else if (ob instanceof ComposedSchema) { ComposedSchema cm = (ComposedSchema)ob; diff --git a/src/test/java/it/imolainformatica/openapi2jsonschema4j/test/TestGenerationFromOAS3.java b/src/test/java/it/imolainformatica/openapi2jsonschema4j/test/TestGenerationFromOAS3.java index 72e32a1..b894395 100644 --- a/src/test/java/it/imolainformatica/openapi2jsonschema4j/test/TestGenerationFromOAS3.java +++ b/src/test/java/it/imolainformatica/openapi2jsonschema4j/test/TestGenerationFromOAS3.java @@ -28,4 +28,7 @@ public class TestGenerationFromOAS3 extends AbstractIT { @Test public void testOAS3WithAllOf() { testForSwagger("petstoreoas3Allof.json"); } + + @Test + public void testOAS3WithInlineArray() { testForSwagger("petstoreoas3ArrayInline.json"); } } diff --git a/src/test/resources/petstoreoas3ArrayInline.json b/src/test/resources/petstoreoas3ArrayInline.json new file mode 100644 index 0000000..006b726 --- /dev/null +++ b/src/test/resources/petstoreoas3ArrayInline.json @@ -0,0 +1,273 @@ +{ + "openapi": "3.0.2", + "info": { + "title": "Swagger Petstore - OpenAPI 3.0", + "description": "This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about\nSwagger at [https://swagger.io](https://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!\nYou can now help us improve the API whether it's by making changes to the definition itself or to the code.\nThat way, with time, we can improve the API in general, and expose some of the new features in OAS3.\n\n_If you're looking for the Swagger 2.0/OAS 2.0 version of Petstore, then click [here](https://editor.swagger.io/?url=https://petstore.swagger.io/v2/swagger.yaml). Alternatively, you can load via the `Edit > Load Petstore OAS 2.0` menu option!_\n\nSome useful links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "email": "apiteam@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.11" + }, + "externalDocs": { + "description": "Find out more about Swagger", + "url": "http://swagger.io" + }, + "servers": [ + { + "url": "https://petstore3.swagger.io/api/v3" + } + ], + "tags": [ + { + "name": "pet", + "description": "Everything about your Pets", + "externalDocs": { + "description": "Find out more", + "url": "http://swagger.io" + } + }, + { + "name": "store", + "description": "Access to Petstore orders", + "externalDocs": { + "description": "Find out more about our store", + "url": "http://swagger.io" + } + }, + { + "name": "user", + "description": "Operations about user" + } + ], + "paths": { + "/pet": { + "put": { + "tags": [ + "pet" + ], + "summary": "Update an existing pet", + "description": "Update an existing pet by Id", + "operationId": "updatePet", + "requestBody": { + "description": "Update an existent pet in the store", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "required": [ + "name", + "photoUrls" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "name": { + "type": "string", + "example": "doggie" + }, + "category": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 1 + }, + "name": { + "type": "string", + "example": "Dogs" + } + }, + "xml": { + "name": "category" + } + }, + "photoUrls": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "type": "string", + "xml": { + "name": "photoUrl" + } + } + }, + "tags": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "tag" + } + } + }, + "status": { + "type": "string", + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ] + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "required": [ + "name", + "photoUrls" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "name": { + "type": "string", + "example": "doggie" + }, + "category": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 1 + }, + "name": { + "type": "string", + "example": "Dogs" + } + }, + "xml": { + "name": "category" + } + }, + "photoUrls": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "type": "string", + "xml": { + "name": "photoUrl" + } + } + }, + "tags": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "tag" + } + } + }, + "status": { + "type": "string", + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ] + } + } + } + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + }, + "422": { + "description": "Validation exception" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + } + }, + "components": { + "securitySchemes": { + "petstore_auth": { + "type": "oauth2", + "flows": { + "implicit": { + "authorizationUrl": "https://petstore3.swagger.io/oauth/authorize", + "scopes": { + "write:pets": "modify pets in your account", + "read:pets": "read your pets" + } + } + } + }, + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "header" + } + } + } +} \ No newline at end of file