forked from loafle/openapi-generator-original
[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)
This commit is contained in:
parent
48e8375166
commit
32bf99a39f
@ -83,7 +83,7 @@ import java.io.IOException
|
|||||||
{{#anyOf}}
|
{{#anyOf}}
|
||||||
{{^isArray}}
|
{{^isArray}}
|
||||||
{{^vendorExtensions.x-duplicated-data-type}}
|
{{^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}}
|
{{/vendorExtensions.x-duplicated-data-type}}
|
||||||
{{/isArray}}
|
{{/isArray}}
|
||||||
{{#isArray}}
|
{{#isArray}}
|
||||||
@ -122,7 +122,7 @@ import java.io.IOException
|
|||||||
return
|
return
|
||||||
{{/isPrimitiveType}}
|
{{/isPrimitiveType}}
|
||||||
{{^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)
|
elementAdapter.write(out, element)
|
||||||
return
|
return
|
||||||
{{/isPrimitiveType}}
|
{{/isPrimitiveType}}
|
||||||
@ -185,7 +185,7 @@ import java.io.IOException
|
|||||||
for(element in jsonElement.getAsJsonArray()) {
|
for(element in jsonElement.getAsJsonArray()) {
|
||||||
{{#items}}
|
{{#items}}
|
||||||
{{#isNumber}}
|
{{#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())
|
String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString())
|
||||||
}
|
}
|
||||||
{{/isNumber}}
|
{{/isNumber}}
|
||||||
@ -238,4 +238,99 @@ import java.io.IOException
|
|||||||
}.nullSafe() as TypeAdapter<T>
|
}.nullSafe() as TypeAdapter<T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<String>()
|
||||||
|
{{#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()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -83,7 +83,7 @@ import java.io.IOException
|
|||||||
{{#oneOf}}
|
{{#oneOf}}
|
||||||
{{^isArray}}
|
{{^isArray}}
|
||||||
{{^vendorExtensions.x-duplicated-data-type}}
|
{{^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}}
|
{{/vendorExtensions.x-duplicated-data-type}}
|
||||||
{{/isArray}}
|
{{/isArray}}
|
||||||
{{#isArray}}
|
{{#isArray}}
|
||||||
@ -122,7 +122,7 @@ import java.io.IOException
|
|||||||
return
|
return
|
||||||
{{/isPrimitiveType}}
|
{{/isPrimitiveType}}
|
||||||
{{^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)
|
elementAdapter.write(out, element)
|
||||||
return
|
return
|
||||||
{{/isPrimitiveType}}
|
{{/isPrimitiveType}}
|
||||||
@ -179,7 +179,7 @@ import java.io.IOException
|
|||||||
for(element in jsonElement.getAsJsonArray()) {
|
for(element in jsonElement.getAsJsonArray()) {
|
||||||
{{#items}}
|
{{#items}}
|
||||||
{{#isNumber}}
|
{{#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())
|
String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString())
|
||||||
}
|
}
|
||||||
{{/isNumber}}
|
{{/isNumber}}
|
||||||
@ -236,4 +236,99 @@ import java.io.IOException
|
|||||||
}.nullSafe() as TypeAdapter<T>
|
}.nullSafe() as TypeAdapter<T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<String>()
|
||||||
|
{{#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()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -22,7 +22,7 @@ import static org.openapitools.codegen.TestUtils.assertFileContains;
|
|||||||
|
|
||||||
public class KotlinClientCodegenApiTest {
|
public class KotlinClientCodegenApiTest {
|
||||||
|
|
||||||
@DataProvider(name = "pathResponses")
|
@DataProvider(name = "clientLibraries")
|
||||||
public Object[][] pathResponses() {
|
public Object[][] pathResponses() {
|
||||||
return new Object[][]{
|
return new Object[][]{
|
||||||
{ClientLibrary.JVM_KTOR},
|
{ClientLibrary.JVM_KTOR},
|
||||||
@ -36,7 +36,7 @@ public class KotlinClientCodegenApiTest {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dataProvider = "pathResponses")
|
@Test(dataProvider = "clientLibraries")
|
||||||
void testPathVariableIsNotEscaped_19930(ClientLibrary library) throws IOException {
|
void testPathVariableIsNotEscaped_19930(ClientLibrary library) throws IOException {
|
||||||
|
|
||||||
OpenAPI openAPI = new OpenAPIParser()
|
OpenAPI openAPI = new OpenAPIParser()
|
||||||
@ -76,29 +76,4 @@ public class KotlinClientCodegenApiTest {
|
|||||||
codegen.additionalProperties().put(KotlinClientCodegen.DATE_LIBRARY, "kotlinx-datetime");
|
codegen.additionalProperties().put(KotlinClientCodegen.DATE_LIBRARY, "kotlinx-datetime");
|
||||||
return codegen;
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -433,6 +433,66 @@ public class KotlinClientCodegenModelTest {
|
|||||||
configAssert.assertValue(KotlinClientCodegen.FAIL_ON_UNKNOWN_PROPERTIES, codegen::isFailOnUnknownProperties, Boolean.FALSE);
|
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 static class ModelNameTest {
|
||||||
private final String expectedName;
|
private final String expectedName;
|
||||||
private final String expectedClassName;
|
private final String expectedClassName;
|
||||||
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -111,4 +111,43 @@ data class ApiAnyOfUserOrPet(var actualInstance: Any? = null) {
|
|||||||
}.nullSafe() as TypeAdapter<T>
|
}.nullSafe() as TypeAdapter<T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<String>()
|
||||||
|
// 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()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,4 +144,61 @@ data class ApiAnyOfUserOrPetOrArrayString(var actualInstance: Any? = null) {
|
|||||||
}.nullSafe() as TypeAdapter<T>
|
}.nullSafe() as TypeAdapter<T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<String>()
|
||||||
|
// 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<kotlin.String>
|
||||||
|
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<kotlin.String> 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()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,4 +115,43 @@ data class ApiUserOrPet(var actualInstance: Any? = null) {
|
|||||||
}.nullSafe() as TypeAdapter<T>
|
}.nullSafe() as TypeAdapter<T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<String>()
|
||||||
|
// 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()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,4 +147,61 @@ data class ApiUserOrPetOrArrayString(var actualInstance: Any? = null) {
|
|||||||
}.nullSafe() as TypeAdapter<T>
|
}.nullSafe() as TypeAdapter<T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<String>()
|
||||||
|
// 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<kotlin.String>
|
||||||
|
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<kotlin.String> 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()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user