From 32bf99a39f9cef816c81e08cf7c8a2dfa024d0de Mon Sep 17 00:00:00 2001 From: Tomasz Letachowicz Date: Tue, 29 Oct 2024 12:38:11 +0100 Subject: [PATCH] [BUG][KOTLIN] Sanitize names of the adapter variables in anyOf and oneOf model template to avoid compilation errors (#19981) * [kotlin] Sanitize one_of and any_of model variable names to avoid compilation errors (#19942) * [kotlin] add missing validateJsonElement method to oneOf and anyOf model templates (#19942) --- .../kotlin-client/anyof_class.mustache | 101 +++++++++++++++++- .../kotlin-client/oneof_class.mustache | 101 +++++++++++++++++- .../codegen/kotlin/ClientLibrary.java | 29 +++++ .../kotlin/KotlinClientCodegenApiTest.java | 29 +---- .../kotlin/KotlinClientCodegenModelTest.java | 60 +++++++++++ .../src/test/resources/3_0/issue_19942.json | 72 +++++++++++++ .../client/models/ApiAnyOfUserOrPet.kt | 39 +++++++ .../models/ApiAnyOfUserOrPetOrArrayString.kt | 57 ++++++++++ .../client/models/ApiUserOrPet.kt | 39 +++++++ .../models/ApiUserOrPetOrArrayString.kt | 57 ++++++++++ 10 files changed, 551 insertions(+), 33 deletions(-) create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/ClientLibrary.java create mode 100644 modules/openapi-generator/src/test/resources/3_0/issue_19942.json diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/anyof_class.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/anyof_class.mustache index a745e7745f0..bac91b313f9 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/anyof_class.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/anyof_class.mustache @@ -83,7 +83,7 @@ import java.io.IOException {{#anyOf}} {{^isArray}} {{^vendorExtensions.x-duplicated-data-type}} - val adapter{{{dataType}}} = gson.getDelegateAdapter(this, TypeToken.get({{{dataType}}}::class.java)) + val adapter{{#sanitizeGeneric}}{{{dataType}}}{{/sanitizeGeneric}} = gson.getDelegateAdapter(this, TypeToken.get({{{dataType}}}::class.java)) {{/vendorExtensions.x-duplicated-data-type}} {{/isArray}} {{#isArray}} @@ -122,7 +122,7 @@ import java.io.IOException return {{/isPrimitiveType}} {{^isPrimitiveType}} - val element = adapter{{{dataType}}}.toJsonTree(value.actualInstance as {{{dataType}}}?) + val element = adapter{{#sanitizeGeneric}}{{{dataType}}}{{/sanitizeGeneric}}.toJsonTree(value.actualInstance as {{{dataType}}}?) elementAdapter.write(out, element) return {{/isPrimitiveType}} @@ -185,7 +185,7 @@ import java.io.IOException for(element in jsonElement.getAsJsonArray()) { {{#items}} {{#isNumber}} - require(jsonElement.getAsJsonPrimitive().isNumber) { + require(element.getAsJsonPrimitive().isNumber) { String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString()) } {{/isNumber}} @@ -238,4 +238,99 @@ import java.io.IOException }.nullSafe() as TypeAdapter } } + + companion object { + /** + * Validates the JSON Element and throws an exception if issues found + * + * @param jsonElement JSON Element + * @throws IOException if the JSON Element is invalid with respect to {{classname}} + */ + @Throws(IOException::class) + fun validateJsonElement(jsonElement: JsonElement?) { + requireNotNull(jsonElement) { + "Provided json element must not be null" + } + var match = 0 + val errorMessages = ArrayList() + {{#composedSchemas}} + {{#anyOf}} + {{^vendorExtensions.x-duplicated-data-type}} + {{^hasVars}} + // validate the json string with {{{dataType}}} + try { + // validate the JSON object to see if any exception is thrown + {{^isArray}} + {{#isNumber}} + require(jsonElement.getAsJsonPrimitive().isNumber()) { + String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString()) + } + {{/isNumber}} + {{^isNumber}} + {{#isPrimitiveType}} + require(jsonElement.getAsJsonPrimitive().is{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}}()) { + String.format("Expected json element to be of type {{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}} in the JSON string but got `%s`", jsonElement.toString()) + } + {{/isPrimitiveType}} + {{/isNumber}} + {{^isNumber}} + {{^isPrimitiveType}} + {{{dataType}}}.validateJsonElement(jsonElement) + {{/isPrimitiveType}} + {{/isNumber}} + {{/isArray}} + {{#isArray}} + require(jsonElement.isJsonArray) { + String.format("Expected json element to be a array type in the JSON string but got `%s`", jsonElement.toString()) + } + + // validate array items + for(element in jsonElement.getAsJsonArray()) { + {{#items}} + {{#isNumber}} + require(element.getAsJsonPrimitive().isNumber) { + String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString()) + } + {{/isNumber}} + {{^isNumber}} + {{#isPrimitiveType}} + require(element.getAsJsonPrimitive().is{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}}) { + String.format("Expected array items to be of type {{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}} in the JSON string but got `%s`", jsonElement.toString()) + } + {{/isPrimitiveType}} + {{/isNumber}} + {{^isNumber}} + {{^isPrimitiveType}} + {{{dataType}}}.validateJsonElement(element) + {{/isPrimitiveType}} + {{/isNumber}} + {{/items}} + } + {{/isArray}} + match++ + } catch (e: Exception) { + // Validation failed, continue + errorMessages.add(String.format("Validation for {{{dataType}}} failed with `%s`.", e.message)) + } + {{/hasVars}} + {{#hasVars}} + // validate json string for {{{.}}} + try { + // validate the JSON object to see if any exception is thrown + {{.}}.validateJsonElement(jsonElement) + match++ + } catch (e: Exception) { + // validation failed, continue + errorMessages.add(String.format("Validation for {{{.}}} failed with `%s`.", e.message)) + } + {{/hasVars}} + {{/vendorExtensions.x-duplicated-data-type}} + {{/anyOf}} + {{/composedSchemas}} + + if (match != 1) { + throw IOException(String.format("Failed validation for {{classname}}: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonElement.toString())) + } + } + } } \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/oneof_class.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/oneof_class.mustache index eebf9858773..a7d43e97acc 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-client/oneof_class.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-client/oneof_class.mustache @@ -83,7 +83,7 @@ import java.io.IOException {{#oneOf}} {{^isArray}} {{^vendorExtensions.x-duplicated-data-type}} - val adapter{{{dataType}}} = gson.getDelegateAdapter(this, TypeToken.get({{{dataType}}}::class.java)) + val adapter{{#sanitizeGeneric}}{{{dataType}}}{{/sanitizeGeneric}} = gson.getDelegateAdapter(this, TypeToken.get({{{dataType}}}::class.java)) {{/vendorExtensions.x-duplicated-data-type}} {{/isArray}} {{#isArray}} @@ -122,7 +122,7 @@ import java.io.IOException return {{/isPrimitiveType}} {{^isPrimitiveType}} - val element = adapter{{{dataType}}}.toJsonTree(value.actualInstance as {{{dataType}}}?) + val element = adapter{{#sanitizeGeneric}}{{{dataType}}}{{/sanitizeGeneric}}.toJsonTree(value.actualInstance as {{{dataType}}}?) elementAdapter.write(out, element) return {{/isPrimitiveType}} @@ -179,7 +179,7 @@ import java.io.IOException for(element in jsonElement.getAsJsonArray()) { {{#items}} {{#isNumber}} - require(jsonElement.getAsJsonPrimitive().isNumber) { + require(element.getAsJsonPrimitive().isNumber) { String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString()) } {{/isNumber}} @@ -236,4 +236,99 @@ import java.io.IOException }.nullSafe() as TypeAdapter } } + + companion object { + /** + * Validates the JSON Element and throws an exception if issues found + * + * @param jsonElement JSON Element + * @throws IOException if the JSON Element is invalid with respect to {{classname}} + */ + @Throws(IOException::class) + fun validateJsonElement(jsonElement: JsonElement?) { + requireNotNull(jsonElement) { + "Provided json element must not be null" + } + var match = 0 + val errorMessages = ArrayList() + {{#composedSchemas}} + {{#oneOf}} + {{^vendorExtensions.x-duplicated-data-type}} + {{^hasVars}} + // validate the json string with {{{dataType}}} + try { + // validate the JSON object to see if any exception is thrown + {{^isArray}} + {{#isNumber}} + require(jsonElement.getAsJsonPrimitive().isNumber()) { + String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString()) + } + {{/isNumber}} + {{^isNumber}} + {{#isPrimitiveType}} + require(jsonElement.getAsJsonPrimitive().is{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}}()) { + String.format("Expected json element to be of type {{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}} in the JSON string but got `%s`", jsonElement.toString()) + } + {{/isPrimitiveType}} + {{/isNumber}} + {{^isNumber}} + {{^isPrimitiveType}} + {{{dataType}}}.validateJsonElement(jsonElement) + {{/isPrimitiveType}} + {{/isNumber}} + {{/isArray}} + {{#isArray}} + require(jsonElement.isJsonArray) { + String.format("Expected json element to be a array type in the JSON string but got `%s`", jsonElement.toString()) + } + + // validate array items + for(element in jsonElement.getAsJsonArray()) { + {{#items}} + {{#isNumber}} + require(jsonElement.getAsJsonPrimitive().isNumber) { + String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString()) + } + {{/isNumber}} + {{^isNumber}} + {{#isPrimitiveType}} + require(element.getAsJsonPrimitive().is{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}}) { + String.format("Expected array items to be of type {{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}} in the JSON string but got `%s`", jsonElement.toString()) + } + {{/isPrimitiveType}} + {{/isNumber}} + {{^isNumber}} + {{^isPrimitiveType}} + {{{dataType}}}.validateJsonElement(element) + {{/isPrimitiveType}} + {{/isNumber}} + {{/items}} + } + {{/isArray}} + match++ + } catch (e: Exception) { + // Validation failed, continue + errorMessages.add(String.format("Validation for {{{dataType}}} failed with `%s`.", e.message)) + } + {{/hasVars}} + {{#hasVars}} + // validate json string for {{{.}}} + try { + // validate the JSON object to see if any exception is thrown + {{.}}.validateJsonElement(jsonElement) + match++ + } catch (e: Exception) { + // validation failed, continue + errorMessages.add(String.format("Validation for {{{.}}} failed with `%s`.", e.message)) + } + {{/hasVars}} + {{/vendorExtensions.x-duplicated-data-type}} + {{/oneOf}} + {{/composedSchemas}} + + if (match != 1) { + throw IOException(String.format("Failed validation for {{classname}}: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonElement.toString())) + } + } + } } \ No newline at end of file diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/ClientLibrary.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/ClientLibrary.java new file mode 100644 index 00000000000..cfb09f3a582 --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/ClientLibrary.java @@ -0,0 +1,29 @@ +package org.openapitools.codegen.kotlin; + +import lombok.Getter; +import org.jetbrains.kotlin.com.intellij.openapi.util.text.Strings; + +@Getter +enum ClientLibrary { + JVM_KTOR("main/kotlin"), + JVM_OKHTTP4("main/kotlin"), + JVM_SPRING_WEBCLIENT("main/kotlin"), + JVM_SPRING_RESTCLIENT("main/kotlin"), + JVM_RETROFIT2("main/kotlin"), + MULTIPLATFORM("commonMain/kotlin"), + JVM_VOLLEY("gson", "main/java"), + JVM_VERTX("main/kotlin"); + private final String serializationLibrary; + private final String libraryName; + private final String sourceRoot; + + ClientLibrary(String serializationLibrary, String sourceRoot) { + this.serializationLibrary = serializationLibrary; + this.sourceRoot = sourceRoot; + this.libraryName = Strings.toLowerCase(this.name()).replace("_", "-"); + } + + ClientLibrary(String sourceRoot) { + this("jackson", sourceRoot); + } +} diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenApiTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenApiTest.java index 4349e88d443..16e7e6e6457 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenApiTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenApiTest.java @@ -22,7 +22,7 @@ import static org.openapitools.codegen.TestUtils.assertFileContains; public class KotlinClientCodegenApiTest { - @DataProvider(name = "pathResponses") + @DataProvider(name = "clientLibraries") public Object[][] pathResponses() { return new Object[][]{ {ClientLibrary.JVM_KTOR}, @@ -36,7 +36,7 @@ public class KotlinClientCodegenApiTest { }; } - @Test(dataProvider = "pathResponses") + @Test(dataProvider = "clientLibraries") void testPathVariableIsNotEscaped_19930(ClientLibrary library) throws IOException { OpenAPI openAPI = new OpenAPIParser() @@ -76,29 +76,4 @@ public class KotlinClientCodegenApiTest { codegen.additionalProperties().put(KotlinClientCodegen.DATE_LIBRARY, "kotlinx-datetime"); return codegen; } - - @Getter - private enum ClientLibrary { - JVM_KTOR("main/kotlin"), - JVM_OKHTTP4("main/kotlin"), - JVM_SPRING_WEBCLIENT("main/kotlin"), - JVM_SPRING_RESTCLIENT("main/kotlin"), - JVM_RETROFIT2("main/kotlin"), - MULTIPLATFORM("commonMain/kotlin"), - JVM_VOLLEY("gson", "main/java"), - JVM_VERTX("main/kotlin"); - private final String serializationLibrary; - private final String libraryName; - private final String sourceRoot; - - ClientLibrary(String serializationLibrary, String sourceRoot) { - this.serializationLibrary = serializationLibrary; - this.sourceRoot = sourceRoot; - this.libraryName = Strings.toLowerCase(this.name()).replace("_", "-"); - } - - ClientLibrary(String sourceRoot) { - this("jackson", sourceRoot); - } - } } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java index f3026827af7..7834549424b 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java @@ -433,6 +433,66 @@ public class KotlinClientCodegenModelTest { configAssert.assertValue(KotlinClientCodegen.FAIL_ON_UNKNOWN_PROPERTIES, codegen::isFailOnUnknownProperties, Boolean.FALSE); } + @DataProvider(name = "gsonClientLibraries") + public Object[][] pathResponses() { + return new Object[][]{ + {ClientLibrary.JVM_KTOR}, + {ClientLibrary.JVM_OKHTTP4}, + {ClientLibrary.JVM_RETROFIT2}, + {ClientLibrary.MULTIPLATFORM}, + {ClientLibrary.JVM_VOLLEY}, + {ClientLibrary.JVM_VERTX} + }; + } + + @Test(dataProvider = "gsonClientLibraries") + public void testLocalVariablesUseSanitizedDataTypeNamesForOneOfProperty_19942(ClientLibrary clientLibrary) throws IOException { + File output = Files.createTempDirectory("test").toFile(); + String path = output.getAbsolutePath(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("kotlin") + .setLibrary(clientLibrary.getLibraryName()) + .setInputSpec("src/test/resources/3_0/issue_19942.json") + .addAdditionalProperty("omitGradleWrapper", true) + .addAdditionalProperty("serializationLibrary", "gson") + .addAdditionalProperty("dateLibrary", "kotlinx-datetime") + .addAdditionalProperty("useSpringBoot3", "true") + .addAdditionalProperty("generateOneOfAnyOfWrappers", true) + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + DefaultGenerator generator = new DefaultGenerator(); + + generator.opts(configurator.toClientOptInput()).generate(); + + TestUtils.assertFileNotContains(Paths.get(path + "/src/" + clientLibrary.getSourceRoot() + "/org/openapitools/client/models/ObjectWithComplexOneOfId.kt"), + "val adapterkotlin.String", "val adapterjava.math.BigDecimal"); + } + + @Test(dataProvider = "gsonClientLibraries") + public void testLocalVariablesUseSanitizedDataTypeNamesForAnyOfProperty_19942(ClientLibrary clientLibrary) throws IOException { + File output = Files.createTempDirectory("test").toFile(); + String path = output.getAbsolutePath(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("kotlin") + .setLibrary(clientLibrary.getLibraryName()) + .setInputSpec("src/test/resources/3_0/issue_19942.json") + .addAdditionalProperty("omitGradleWrapper", true) + .addAdditionalProperty("serializationLibrary", "gson") + .addAdditionalProperty("dateLibrary", "kotlinx-datetime") + .addAdditionalProperty("useSpringBoot3", "true") + .addAdditionalProperty("generateOneOfAnyOfWrappers", true) + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + DefaultGenerator generator = new DefaultGenerator(); + + generator.opts(configurator.toClientOptInput()).generate(); + + TestUtils.assertFileNotContains(Paths.get(path + "/src/" + clientLibrary.getSourceRoot() + "/org/openapitools/client/models/ObjectWithComplexAnyOfId.kt"), + "val adapterkotlin.String", "val adapterjava.math.BigDecimal"); + } + private static class ModelNameTest { private final String expectedName; private final String expectedClassName; diff --git a/modules/openapi-generator/src/test/resources/3_0/issue_19942.json b/modules/openapi-generator/src/test/resources/3_0/issue_19942.json new file mode 100644 index 00000000000..5f9d618dc56 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/issue_19942.json @@ -0,0 +1,72 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "xxxxx", + "version": "1.0" + }, + "servers": [ + { + "url": "https://xxxxx" + }, + { + "url": "http://localhost:3000" + } + ], + "paths": { + "/test": { + "get": { + "operationId": "testOneOf", + "tags": [ + "testOneOf" + ], + "summary": "fetches oneOf id", + "responses": { + "200": { + "description": "ok", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectWithComplexOneOf" + } + } + } + } + } + } + } + }, + "components" : { + "schemas": { + "ObjectWithComplexOneOf" : { + "type": "object", + "properties": { + "id": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + }, + "ObjectWithComplexAnyOf" : { + "type": "object", + "properties": { + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + } + } + } +} \ No newline at end of file diff --git a/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiAnyOfUserOrPet.kt b/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiAnyOfUserOrPet.kt index 3d523a450ea..e7c337f2ebd 100644 --- a/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiAnyOfUserOrPet.kt +++ b/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiAnyOfUserOrPet.kt @@ -111,4 +111,43 @@ data class ApiAnyOfUserOrPet(var actualInstance: Any? = null) { }.nullSafe() as TypeAdapter } } + + companion object { + /** + * Validates the JSON Element and throws an exception if issues found + * + * @param jsonElement JSON Element + * @throws IOException if the JSON Element is invalid with respect to ApiAnyOfUserOrPet + */ + @Throws(IOException::class) + fun validateJsonElement(jsonElement: JsonElement?) { + requireNotNull(jsonElement) { + "Provided json element must not be null" + } + var match = 0 + val errorMessages = ArrayList() + // validate the json string with ApiUser + try { + // validate the JSON object to see if any exception is thrown + ApiUser.validateJsonElement(jsonElement) + match++ + } catch (e: Exception) { + // Validation failed, continue + errorMessages.add(String.format("Validation for ApiUser failed with `%s`.", e.message)) + } + // validate the json string with ApiPet + try { + // validate the JSON object to see if any exception is thrown + ApiPet.validateJsonElement(jsonElement) + match++ + } catch (e: Exception) { + // Validation failed, continue + errorMessages.add(String.format("Validation for ApiPet failed with `%s`.", e.message)) + } + + if (match != 1) { + throw IOException(String.format("Failed validation for ApiAnyOfUserOrPet: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonElement.toString())) + } + } + } } diff --git a/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiAnyOfUserOrPetOrArrayString.kt b/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiAnyOfUserOrPetOrArrayString.kt index 1ec7549f45c..4f908f69079 100644 --- a/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiAnyOfUserOrPetOrArrayString.kt +++ b/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiAnyOfUserOrPetOrArrayString.kt @@ -144,4 +144,61 @@ data class ApiAnyOfUserOrPetOrArrayString(var actualInstance: Any? = null) { }.nullSafe() as TypeAdapter } } + + companion object { + /** + * Validates the JSON Element and throws an exception if issues found + * + * @param jsonElement JSON Element + * @throws IOException if the JSON Element is invalid with respect to ApiAnyOfUserOrPetOrArrayString + */ + @Throws(IOException::class) + fun validateJsonElement(jsonElement: JsonElement?) { + requireNotNull(jsonElement) { + "Provided json element must not be null" + } + var match = 0 + val errorMessages = ArrayList() + // validate the json string with ApiUser + try { + // validate the JSON object to see if any exception is thrown + ApiUser.validateJsonElement(jsonElement) + match++ + } catch (e: Exception) { + // Validation failed, continue + errorMessages.add(String.format("Validation for ApiUser failed with `%s`.", e.message)) + } + // validate the json string with ApiPet + try { + // validate the JSON object to see if any exception is thrown + ApiPet.validateJsonElement(jsonElement) + match++ + } catch (e: Exception) { + // Validation failed, continue + errorMessages.add(String.format("Validation for ApiPet failed with `%s`.", e.message)) + } + // validate the json string with kotlin.collections.List + try { + // validate the JSON object to see if any exception is thrown + require(jsonElement.isJsonArray) { + String.format("Expected json element to be a array type in the JSON string but got `%s`", jsonElement.toString()) + } + + // validate array items + for(element in jsonElement.getAsJsonArray()) { + require(element.getAsJsonPrimitive().isString) { + String.format("Expected array items to be of type String in the JSON string but got `%s`", jsonElement.toString()) + } + } + match++ + } catch (e: Exception) { + // Validation failed, continue + errorMessages.add(String.format("Validation for kotlin.collections.List failed with `%s`.", e.message)) + } + + if (match != 1) { + throw IOException(String.format("Failed validation for ApiAnyOfUserOrPetOrArrayString: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonElement.toString())) + } + } + } } diff --git a/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiUserOrPet.kt b/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiUserOrPet.kt index 372906b0e56..5922d174655 100644 --- a/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiUserOrPet.kt +++ b/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiUserOrPet.kt @@ -115,4 +115,43 @@ data class ApiUserOrPet(var actualInstance: Any? = null) { }.nullSafe() as TypeAdapter } } + + companion object { + /** + * Validates the JSON Element and throws an exception if issues found + * + * @param jsonElement JSON Element + * @throws IOException if the JSON Element is invalid with respect to ApiUserOrPet + */ + @Throws(IOException::class) + fun validateJsonElement(jsonElement: JsonElement?) { + requireNotNull(jsonElement) { + "Provided json element must not be null" + } + var match = 0 + val errorMessages = ArrayList() + // validate the json string with ApiUser + try { + // validate the JSON object to see if any exception is thrown + ApiUser.validateJsonElement(jsonElement) + match++ + } catch (e: Exception) { + // Validation failed, continue + errorMessages.add(String.format("Validation for ApiUser failed with `%s`.", e.message)) + } + // validate the json string with ApiPet + try { + // validate the JSON object to see if any exception is thrown + ApiPet.validateJsonElement(jsonElement) + match++ + } catch (e: Exception) { + // Validation failed, continue + errorMessages.add(String.format("Validation for ApiPet failed with `%s`.", e.message)) + } + + if (match != 1) { + throw IOException(String.format("Failed validation for ApiUserOrPet: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonElement.toString())) + } + } + } } diff --git a/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiUserOrPetOrArrayString.kt b/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiUserOrPetOrArrayString.kt index 009b3bef523..060b98933e6 100644 --- a/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiUserOrPetOrArrayString.kt +++ b/samples/client/petstore/kotlin-model-prefix-type-mappings/src/main/kotlin/org/openapitools/client/models/ApiUserOrPetOrArrayString.kt @@ -147,4 +147,61 @@ data class ApiUserOrPetOrArrayString(var actualInstance: Any? = null) { }.nullSafe() as TypeAdapter } } + + companion object { + /** + * Validates the JSON Element and throws an exception if issues found + * + * @param jsonElement JSON Element + * @throws IOException if the JSON Element is invalid with respect to ApiUserOrPetOrArrayString + */ + @Throws(IOException::class) + fun validateJsonElement(jsonElement: JsonElement?) { + requireNotNull(jsonElement) { + "Provided json element must not be null" + } + var match = 0 + val errorMessages = ArrayList() + // validate the json string with ApiUser + try { + // validate the JSON object to see if any exception is thrown + ApiUser.validateJsonElement(jsonElement) + match++ + } catch (e: Exception) { + // Validation failed, continue + errorMessages.add(String.format("Validation for ApiUser failed with `%s`.", e.message)) + } + // validate the json string with ApiPet + try { + // validate the JSON object to see if any exception is thrown + ApiPet.validateJsonElement(jsonElement) + match++ + } catch (e: Exception) { + // Validation failed, continue + errorMessages.add(String.format("Validation for ApiPet failed with `%s`.", e.message)) + } + // validate the json string with kotlin.collections.List + try { + // validate the JSON object to see if any exception is thrown + require(jsonElement.isJsonArray) { + String.format("Expected json element to be a array type in the JSON string but got `%s`", jsonElement.toString()) + } + + // validate array items + for(element in jsonElement.getAsJsonArray()) { + require(element.getAsJsonPrimitive().isString) { + String.format("Expected array items to be of type String in the JSON string but got `%s`", jsonElement.toString()) + } + } + match++ + } catch (e: Exception) { + // Validation failed, continue + errorMessages.add(String.format("Validation for kotlin.collections.List failed with `%s`.", e.message)) + } + + if (match != 1) { + throw IOException(String.format("Failed validation for ApiUserOrPetOrArrayString: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonElement.toString())) + } + } + } }