diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenProperty.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenProperty.java index da21e3416bc..de026b2d3e0 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenProperty.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenProperty.java @@ -59,7 +59,9 @@ public class CodegenProperty implements Cloneable { public boolean isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isByteArray, isBinary, isFile, isBoolean, isDate, isDateTime, isUuid; public boolean isListContainer, isMapContainer; public boolean isEnum; - public boolean isReadOnly = false; + public boolean isReadOnly; + public boolean isWriteOnly; + public boolean isNullable; public List _enum; public Map allowableValues; public CodegenProperty items; @@ -437,6 +439,8 @@ public class CodegenProperty implements Cloneable { result = prime * result + ((isNotContainer ? 13:31)); result = prime * result + ((isPrimitiveType ? 13:31)); result = prime * result + ((isReadOnly ? 13:31)); + result = prime * result + ((isWriteOnly ? 13:31)); + result = prime * result + ((isNullable ? 13:31)); result = prime * result + ((items == null) ? 0 : items.hashCode()); result = prime * result + ((mostInnerItems == null) ? 0 : mostInnerItems.hashCode()); result = prime * result + ((jsonSchema == null) ? 0 : jsonSchema.hashCode()); @@ -587,6 +591,12 @@ public class CodegenProperty implements Cloneable { if (this.isReadOnly != other.isReadOnly) { return false; } + if (this.isWriteOnly != other.isWriteOnly) { + return false; + } + if (this.isNullable != other.isNullable) { + return false; + } if (this._enum != other._enum && (this._enum == null || !this._enum.equals(other._enum))) { return false; } @@ -769,6 +779,8 @@ public class CodegenProperty implements Cloneable { ", isMapContainer=" + isMapContainer + ", isEnum=" + isEnum + ", isReadOnly=" + isReadOnly + + ", isWriteOnly=" + isWriteOnly+ + ", isNullable=" + isNullable + ", _enum=" + _enum + ", allowableValues=" + allowableValues + ", items=" + items + diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index fdf17ee6612..61d1ae83155 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -185,7 +185,7 @@ public class DefaultCodegen implements CodegenConfig { .get(CodegenConstants.REMOVE_OPERATION_ID_PREFIX).toString())); } - if (additionalProperties.containsKey(CodegenConstants.DOCEXTENSION)){ + if (additionalProperties.containsKey(CodegenConstants.DOCEXTENSION)) { this.setDocExtension(String.valueOf(additionalProperties .get(CodegenConstants.DOCEXTENSION).toString())); } @@ -771,7 +771,7 @@ public class DefaultCodegen implements CodegenConfig { public String toVarName(String name) { if (reservedWords.contains(name)) { return escapeReservedWord(name); - } else if (((CharSequence) name).chars().anyMatch(character -> specialCharReplacements.keySet().contains( "" + ((char) character)))) { + } else if (((CharSequence) name).chars().anyMatch(character -> specialCharReplacements.keySet().contains("" + ((char) character)))) { return escapeSpecialCharacters(name, null, null); } else { return name; @@ -789,7 +789,7 @@ public class DefaultCodegen implements CodegenConfig { name = removeNonNameElementToCamelCase(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. if (reservedWords.contains(name)) { return escapeReservedWord(name); - } else if (((CharSequence) name).chars().anyMatch(character -> specialCharReplacements.keySet().contains( "" + ((char) character)))) { + } else if (((CharSequence) name).chars().anyMatch(character -> specialCharReplacements.keySet().contains("" + ((char) character)))) { return escapeSpecialCharacters(name, null, null); } return name; @@ -832,8 +832,8 @@ public class DefaultCodegen implements CodegenConfig { /** * Return the name with escaped characters. * - * @param name the name to be escaped - * @param charactersToAllow characters that are not escaped + * @param name the name to be escaped + * @param charactersToAllow characters that are not escaped * @param appdendixToReplacement String to append to replaced characters. * @return the escaped word *

@@ -841,15 +841,15 @@ public class DefaultCodegen implements CodegenConfig { */ public String escapeSpecialCharacters(String name, List charactersToAllow, String appdendixToReplacement) { String result = (String) ((CharSequence) name).chars().mapToObj(c -> { - String character = "" + (char) c; - if (charactersToAllow != null && charactersToAllow.contains(character)) { - return character; - } else if (specialCharReplacements.containsKey(character)) { - return specialCharReplacements.get(character) + (appdendixToReplacement != null ? appdendixToReplacement: ""); - } else { - return character; - } - }).reduce( (c1, c2) -> "" + c1 + c2).orElse(null); + String character = "" + (char) c; + if (charactersToAllow != null && charactersToAllow.contains(character)) { + return character; + } else if (specialCharReplacements.containsKey(character)) { + return specialCharReplacements.get(character) + (appdendixToReplacement != null ? appdendixToReplacement : ""); + } else { + return character; + } + }).reduce((c1, c2) -> "" + c1 + c2).orElse(null); if (result != null) return result; throw new RuntimeException("Word '" + name + "' could not be escaped."); @@ -1683,13 +1683,13 @@ public class DefaultCodegen implements CodegenConfig { } private CodegenDiscriminator createDiscriminator(String schemaName, Schema schema, Map allDefinitions) { - if(schema.getDiscriminator() == null) { + if (schema.getDiscriminator() == null) { return null; } CodegenDiscriminator discriminator = new CodegenDiscriminator(); discriminator.setPropertyName(schema.getDiscriminator().getPropertyName()); discriminator.setMapping(schema.getDiscriminator().getMapping()); - if(schema.getDiscriminator().getMapping() != null && !schema.getDiscriminator().getMapping().isEmpty()) { + if (schema.getDiscriminator().getMapping() != null && !schema.getDiscriminator().getMapping().isEmpty()) { for (Entry e : schema.getDiscriminator().getMapping().entrySet()) { String name = ModelUtils.getSimpleRef(e.getValue()); discriminator.getMappedModels().add(new MappedModel(e.getKey(), name)); @@ -1698,9 +1698,9 @@ public class DefaultCodegen implements CodegenConfig { allDefinitions.forEach((childName, child) -> { if (child instanceof ComposedSchema && ((ComposedSchema) child).getAllOf() != null) { Set parentSchemas = ((ComposedSchema) child).getAllOf().stream() - .filter(s -> s.get$ref() != null) - .map(s -> ModelUtils.getSimpleRef(s.get$ref())) - .collect(Collectors.toSet()); + .filter(s -> s.get$ref() != null) + .map(s -> ModelUtils.getSimpleRef(s.get$ref())) + .collect(Collectors.toSet()); if (parentSchemas.contains(schemaName)) { discriminator.getMappedModels().add(new MappedModel(childName, childName)); } @@ -1786,6 +1786,13 @@ public class DefaultCodegen implements CodegenConfig { if (p.getReadOnly() != null) { property.isReadOnly = p.getReadOnly(); } + if (p.getWriteOnly() != null) { + property.isWriteOnly = p.getWriteOnly(); + } + if (p.getNullable() != null) { + property.isNullable = p.getNullable(); + } + if (p.getXml() != null) { if (p.getXml().getAttribute() != null) { property.isXmlAttribute = p.getXml().getAttribute(); @@ -2506,7 +2513,7 @@ public class DefaultCodegen implements CodegenConfig { /** * Convert OAS Response object to Codegen Response object * - * @param openAPI a OAS object representing the spec + * @param openAPI a OAS object representing the spec * @param responseCode HTTP response code * @param response OAS Response object * @return Codegen Response object @@ -3495,7 +3502,7 @@ public class DefaultCodegen implements CodegenConfig { */ public String apiDocFilename(String templateName, String tag) { String docExtension = getDocExtension(); - String suffix = docExtension != null ? docExtension: apiDocTemplateFiles().get(templateName); + String suffix = docExtension != null ? docExtension : apiDocTemplateFiles().get(templateName); return apiDocFileFolder() + File.separator + toApiDocFilename(tag) + suffix; } @@ -4430,7 +4437,7 @@ public class DefaultCodegen implements CodegenConfig { } if (StringUtils.isEmpty(bodyParameterName)) { - if(StringUtils.isEmpty(mostInnerItem.complexType)) { + if (StringUtils.isEmpty(mostInnerItem.complexType)) { codegenParameter.baseName = "request_body"; } else { codegenParameter.baseName = mostInnerItem.complexType; @@ -4602,7 +4609,7 @@ public class DefaultCodegen implements CodegenConfig { return Collections.emptyList(); } List codegenServers = new LinkedList<>(); - for (Server server: servers) { + for (Server server : servers) { CodegenServer cs = new CodegenServer(); cs.description = escapeText(server.getDescription()); cs.url = server.getUrl(); @@ -4618,7 +4625,7 @@ public class DefaultCodegen implements CodegenConfig { return Collections.emptyList(); } List codegenServerVariables = new LinkedList<>(); - for (Entry variableEntry: variables.entrySet()) { + for (Entry variableEntry : variables.entrySet()) { CodegenServerVariable codegenServerVariable = new CodegenServerVariable(); ServerVariable variable = variableEntry.getValue(); codegenServerVariable.defaultValue = variable.getDefault(); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java index 6f7bb58ff43..a0c5a326ead 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java @@ -23,6 +23,7 @@ import org.openapitools.codegen.languages.RubyClientCodegen; import io.swagger.parser.OpenAPIParser; import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.parser.core.models.ParseOptions; import org.apache.commons.io.FileUtils; @@ -169,4 +170,61 @@ public class RubyClientCodegenTest { Assert.assertEquals(bp.example, "OnlinePetstore::Pet.new"); } + + @Test(description = "test nullable for properties") + public void nullableTest() { + final OpenAPI openAPI = new OpenAPIParser().readLocation("src/test/resources/3_0/petstore_oas3_test.yaml", null, new ParseOptions()).getOpenAPI(); + final RubyClientCodegen codegen = new RubyClientCodegen(); + codegen.setModuleName("OnlinePetstore"); + final String path = "/pet"; + + final Schema schema = openAPI.getComponents().getSchemas().get("NullablePet"); + CodegenModel nullablePet = codegen.fromModel("NullablePet", schema, openAPI.getComponents().getSchemas()); + CodegenProperty cp0 = nullablePet.getVars().get(0); + Assert.assertTrue(cp0.isNullable); + + CodegenProperty cp1 = nullablePet.getVars().get(1); + Assert.assertFalse(cp1.isNullable); + + CodegenProperty cp2 = nullablePet.getVars().get(2); + Assert.assertTrue(cp2.isNullable); + + CodegenProperty cp3 = nullablePet.getVars().get(3); + Assert.assertTrue(cp3.isNullable); + + CodegenProperty cp4 = nullablePet.getVars().get(4); + Assert.assertFalse(cp4.isNullable); + + CodegenProperty cp5 = nullablePet.getVars().get(5); + Assert.assertTrue(cp5.isNullable); + } + + @Test(description = "test properties without nullable") + public void propertiesWithoutNullableTest() { + final OpenAPI openAPI = new OpenAPIParser().readLocation("src/test/resources/3_0/petstore_oas3_test.yaml", null, new ParseOptions()).getOpenAPI(); + final RubyClientCodegen codegen = new RubyClientCodegen(); + codegen.setModuleName("OnlinePetstore"); + final String path = "/pet"; + + final Schema schema = openAPI.getComponents().getSchemas().get("Pet"); + CodegenModel nullablePet = codegen.fromModel("Pet", schema, openAPI.getComponents().getSchemas()); + CodegenProperty cp0 = nullablePet.getVars().get(0); + Assert.assertFalse(cp0.isNullable); + + CodegenProperty cp1 = nullablePet.getVars().get(1); + Assert.assertFalse(cp1.isNullable); + + CodegenProperty cp2 = nullablePet.getVars().get(2); + Assert.assertFalse(cp2.isNullable); + + CodegenProperty cp3 = nullablePet.getVars().get(3); + Assert.assertFalse(cp3.isNullable); + + CodegenProperty cp4 = nullablePet.getVars().get(4); + Assert.assertFalse(cp4.isNullable); + + CodegenProperty cp5 = nullablePet.getVars().get(5); + Assert.assertFalse(cp5.isNullable); + } + } diff --git a/modules/openapi-generator/src/test/resources/3_0/petstore_oas3_test.yaml b/modules/openapi-generator/src/test/resources/3_0/petstore_oas3_test.yaml new file mode 100644 index 00000000000..c9c83e09a6b --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/petstore_oas3_test.yaml @@ -0,0 +1,741 @@ +openapi: 3.0.0 +servers: + - url: 'http://petstore.swagger.io/v2' +info: + description: >- + A test spec based on the Petstore spec with OAS3 related test cases such as nullable + version: 1.0.0 + title: OpenAPI Petstore + license: + name: Apache-2.0 + url: 'http://www.apache.org/licenses/LICENSE-2.0.html' +tags: + - name: pet + description: Everything about your Pets + - name: store + description: Access to Petstore orders + - name: user + description: Operations about user +paths: + /pet: + post: + tags: + - pet + summary: Add a new pet to the store + description: '' + operationId: addPet + responses: + '405': + description: Invalid input + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + $ref: '#/components/requestBodies/Pet' + put: + tags: + - pet + summary: Update an existing pet + description: '' + operationId: updatePet + responses: + '400': + description: Invalid ID supplied + '404': + description: Pet not found + '405': + description: Validation exception + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + $ref: '#/components/requestBodies/Pet' + /pet/findByStatus: + get: + tags: + - pet + summary: Finds Pets by status + description: Multiple status values can be provided with comma separated strings + operationId: findPetsByStatus + parameters: + - name: status + in: query + description: Status values that need to be considered for filter + required: true + style: form + explode: false + schema: + type: array + items: + type: string + enum: + - available + - pending + - sold + default: available + responses: + '200': + description: successful operation + content: + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid status value + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + /pet/findByTags: + get: + tags: + - pet + summary: Finds Pets by tags + description: >- + Multiple tags can be provided with comma separated strings. Use tag1, + tag2, tag3 for testing. + operationId: findPetsByTags + parameters: + - name: tags + in: query + description: Tags to filter by + required: true + style: form + explode: false + schema: + type: array + items: + type: string + responses: + '200': + description: successful operation + content: + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid tag value + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + deprecated: true + '/pet/{petId}': + get: + tags: + - pet + summary: Find pet by ID + description: Returns a single pet + operationId: getPetById + parameters: + - name: petId + in: path + description: ID of pet to return + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid ID supplied + '404': + description: Pet not found + security: + - api_key: [] + post: + tags: + - pet + summary: Updates a pet in the store with form data + description: '' + operationId: updatePetWithForm + parameters: + - name: petId + in: path + description: ID of pet that needs to be updated + required: true + schema: + type: integer + format: int64 + responses: + '405': + description: Invalid input + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + name: + description: Updated name of the pet + type: string + status: + description: Updated status of the pet + type: string + delete: + tags: + - pet + summary: Deletes a pet + description: '' + operationId: deletePet + parameters: + - name: api_key + in: header + required: false + schema: + type: string + - name: petId + in: path + description: Pet id to delete + required: true + schema: + type: integer + format: int64 + responses: + '400': + description: Invalid pet value + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + '/pet/{petId}/uploadImage': + post: + tags: + - pet + summary: uploads an image + description: '' + operationId: uploadFile + parameters: + - name: petId + in: path + description: ID of pet to update + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + additionalMetadata: + description: Additional data to pass to server + type: string + file: + description: file to upload + type: string + format: binary + /store/inventory: + get: + tags: + - store + summary: Returns pet inventories by status + description: Returns a map of status codes to quantities + operationId: getInventory + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: object + additionalProperties: + type: integer + format: int32 + security: + - api_key: [] + /store/order: + post: + tags: + - store + summary: Place an order for a pet + description: '' + operationId: placeOrder + responses: + '200': + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/json: + schema: + $ref: '#/components/schemas/Order' + '400': + description: Invalid Order + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + description: order placed for purchasing the pet + required: true + '/store/order/{orderId}': + get: + tags: + - store + summary: Find purchase order by ID + description: >- + For valid response try integer IDs with value <= 5 or > 10. Other values + will generated exceptions + operationId: getOrderById + parameters: + - name: orderId + in: path + description: ID of pet that needs to be fetched + required: true + schema: + type: integer + format: int64 + minimum: 1 + maximum: 5 + responses: + '200': + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/json: + schema: + $ref: '#/components/schemas/Order' + '400': + description: Invalid ID supplied + '404': + description: Order not found + delete: + tags: + - store + summary: Delete purchase order by ID + description: >- + For valid response try integer IDs with value < 1000. Anything above + 1000 or nonintegers will generate API errors + operationId: deleteOrder + parameters: + - name: orderId + in: path + description: ID of the order that needs to be deleted + required: true + schema: + type: string + responses: + '400': + description: Invalid ID supplied + '404': + description: Order not found + /user: + post: + tags: + - user + summary: Create user + description: This can only be done by the logged in user. + operationId: createUser + responses: + default: + description: successful operation + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Created user object + required: true + /user/createWithArray: + post: + tags: + - user + summary: Creates list of users with given input array + description: '' + operationId: createUsersWithArrayInput + responses: + default: + description: successful operation + requestBody: + $ref: '#/components/requestBodies/UserArray' + /user/createWithList: + post: + tags: + - user + summary: Creates list of users with given input array + description: '' + operationId: createUsersWithListInput + responses: + default: + description: successful operation + requestBody: + $ref: '#/components/requestBodies/UserArray' + /user/login: + get: + tags: + - user + summary: Logs user into the system + description: '' + operationId: loginUser + parameters: + - name: username + in: query + description: The user name for login + required: true + schema: + type: string + - name: password + in: query + description: The password for login in clear text + required: true + schema: + type: string + responses: + '200': + description: successful operation + headers: + X-Rate-Limit: + description: calls per hour allowed by the user + schema: + type: integer + format: int32 + X-Expires-After: + description: date in UTC when toekn expires + schema: + type: string + format: date-time + content: + application/xml: + schema: + type: string + application/json: + schema: + type: string + '400': + description: Invalid username/password supplied + /user/logout: + get: + tags: + - user + summary: Logs out current logged in user session + description: '' + operationId: logoutUser + responses: + default: + description: successful operation + '/user/{username}': + get: + tags: + - user + summary: Get user by user name + description: '' + operationId: getUserByName + parameters: + - name: username + in: path + description: The name that needs to be fetched. Use user1 for testing. + required: true + schema: + type: string + responses: + '200': + description: successful operation + content: + application/xml: + schema: + $ref: '#/components/schemas/User' + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + description: Invalid username supplied + '404': + description: User not found + put: + tags: + - user + summary: Updated user + description: This can only be done by the logged in user. + operationId: updateUser + parameters: + - name: username + in: path + description: name that need to be deleted + required: true + schema: + type: string + responses: + '400': + description: Invalid user supplied + '404': + description: User not found + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Updated user object + required: true + delete: + tags: + - user + summary: Delete user + description: This can only be done by the logged in user. + operationId: deleteUser + parameters: + - name: username + in: path + description: The name that needs to be deleted + required: true + schema: + type: string + responses: + '400': + description: Invalid username supplied + '404': + description: User not found +externalDocs: + description: Find out more about Swagger + url: 'http://swagger.io' +components: + requestBodies: + UserArray: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + description: List of user object + required: true + Pet: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + description: Pet object that needs to be added to the store + required: true + securitySchemes: + petstore_auth: + type: oauth2 + flows: + implicit: + authorizationUrl: 'http://petstore.swagger.io/api/oauth/dialog' + scopes: + 'write:pets': modify pets in your account + 'read:pets': read your pets + api_key: + type: apiKey + name: api_key + in: header + schemas: + Order: + title: Pet Order + description: An order for a pets from the pet store + type: object + properties: + id: + type: integer + format: int64 + petId: + type: integer + format: int64 + quantity: + type: integer + format: int32 + shipDate: + type: string + format: date-time + status: + type: string + description: Order Status + enum: + - placed + - approved + - delivered + complete: + type: boolean + default: false + xml: + name: Order + Category: + title: Pet category + description: A category for a pet + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + xml: + name: Category + User: + title: a User + description: A User who is purchasing from the pet store + type: object + properties: + id: + type: integer + format: int64 + username: + type: string + firstName: + type: string + lastName: + type: string + email: + type: string + password: + type: string + phone: + type: string + userStatus: + type: integer + format: int32 + description: User Status + xml: + name: User + Tag: + title: Pet Tag + description: A tag for a pet + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + xml: + name: Tag + Pet: + title: a Pet + description: A pet for sale in the pet store + type: object + required: + - name + - photoUrls + properties: + id: + type: integer + format: int64 + category: + $ref: '#/components/schemas/Category' + name: + type: string + example: doggie + photoUrls: + type: array + xml: + name: photoUrl + wrapped: true + items: + type: string + tags: + type: array + xml: + name: tag + wrapped: true + items: + $ref: '#/components/schemas/Tag' + status: + type: string + description: pet status in the store + enum: + - available + - pending + - sold + xml: + name: Pet + NullablePet: + title: a Pet + description: A pet for sale in the pet store + type: object + required: + - name + - photoUrls + properties: + id: + nullable: true + type: integer + format: int64 + category: + $ref: '#/components/schemas/Category' + name: + nullable: true + type: string + example: doggie + photoUrls: + nullable: true + type: array + xml: + name: photoUrl + wrapped: true + items: + type: string + tags: + type: array + xml: + name: tag + wrapped: true + items: + $ref: '#/components/schemas/Tag' + status: + nullable: true + type: string + description: pet status in the store + enum: + - available + - pending + - sold + xml: + name: Pet + ApiResponse: + title: An uploaded response + description: Describes the result of uploading an image resource + type: object + properties: + code: + type: integer + format: int32 + type: + type: string + message: + type: string