Compare commits

..

1 Commits

Author SHA1 Message Date
William Cheng
a3fb9aeef8 Fix HTML entity encoding in plugins documentation 2026-02-03 13:22:48 +08:00
789 changed files with 3466 additions and 25839 deletions

View File

@@ -14,7 +14,6 @@ on:
- samples/client/petstore/java/microprofile-rest-client-outer-enum/**
# servers
- samples/openapi3/server/petstore/springboot-3/**
- samples/server/petstore/springboot-x-implements-skip/**
- samples/server/petstore/java-camel/**
- samples/server/petstore/java-helidon-server/v3/mp/**
- samples/server/petstore/java-helidon-server/v3/se/**
@@ -32,7 +31,6 @@ on:
- samples/client/petstore/java/microprofile-rest-client-outer-enum/**
# servers
- samples/openapi3/server/petstore/springboot-3/**
- samples/server/petstore/springboot-x-implements-skip/**
- samples/server/petstore/java-camel/**
- samples/server/petstore/java-helidon-server/v3/mp/**
- samples/server/petstore/java-helidon-server/v3/se/**
@@ -56,7 +54,6 @@ jobs:
- samples/client/petstore/java/microprofile-rest-client-outer-enum
# servers
- samples/openapi3/server/petstore/springboot-3
- samples/server/petstore/springboot-x-implements-skip
- samples/server/petstore/java-camel/
- samples/server/petstore/java-helidon-server/v3/mp/
- samples/server/petstore/java-helidon-server/v3/se

View File

@@ -20,7 +20,6 @@ jobs:
- samples/client/echo_api/kotlin-jvm-spring-3-restclient
- samples/client/echo_api/kotlin-model-prefix-type-mappings
- samples/client/echo_api/kotlin-jvm-okhttp
- samples/client/echo_api/kotlin-jvm-okhttp-multipart-json
steps:
- uses: actions/checkout@v5
- uses: actions/setup-java@v5

View File

@@ -3,7 +3,6 @@ name: Samples Kotlin server (jdk17)
on:
push:
paths:
- 'samples/server/others/kotlin-server/**'
- 'samples/server/petstore/kotlin-springboot-3*/**'
- 'samples/server/petstore/kotlin-server/**'
- 'samples/server/petstore/kotlin-server-modelMutable/**'
@@ -14,7 +13,6 @@ on:
# - samples/server/petstore/kotlin-spring-default/**
pull_request:
paths:
- 'samples/server/others/kotlin-server/**'
- 'samples/server/petstore/kotlin-springboot-3*/**'
- 'samples/server/petstore/kotlin-server/**'
- 'samples/server/petstore/kotlin-server-modelMutable/**'
@@ -36,10 +34,6 @@ jobs:
matrix:
sample:
# server
- samples/server/others/kotlin-server/polymorphism-allof-and-discriminator
- samples/server/others/kotlin-server/polymorphism-and-discriminator-disabled-jackson-fix
- samples/server/others/kotlin-server/polymorphism-and-discriminator
- samples/server/others/kotlin-server/polymorphism
- samples/server/petstore/kotlin-server-required-and-nullable-properties
- samples/server/petstore/kotlin-springboot-3
- samples/server/petstore/kotlin-springboot-3-no-response-entity

View File

@@ -3,12 +3,10 @@ name: Samples Kotlin server (jdk21)
on:
push:
paths:
- 'samples/server/others/kotlin-server/**'
- 'samples/server/petstore/kotlin-server/**'
- 'samples/server/petstore/kotlin-server-required-and-nullable-properties/**'
pull_request:
paths:
- 'samples/server/others/kotlin-server/**'
- 'samples/server/petstore/kotlin-server/**'
- 'samples/server/petstore/kotlin-server-required-and-nullable-properties/**'
@@ -23,10 +21,6 @@ jobs:
fail-fast: false
matrix:
sample:
- samples/server/others/kotlin-server/polymorphism-allof-and-discriminator
- samples/server/others/kotlin-server/polymorphism-and-discriminator-disabled-jackson-fix
- samples/server/others/kotlin-server/polymorphism-and-discriminator
- samples/server/others/kotlin-server/polymorphism
- samples/server/petstore/kotlin-server/javalin-6
- samples/server/petstore/kotlin-server/ktor
- samples/server/petstore/kotlin-server/ktor2

2
.gitignore vendored
View File

@@ -229,9 +229,7 @@ samples/client/petstore/kotlin*/src/main/kotlin/test/
samples/client/petstore/kotlin*/build/
samples/server/others/kotlin-server/jaxrs-spec/build/
samples/client/echo_api/kotlin-jvm-spring-3-restclient/build/
samples/client/echo_api/kotlin-jvm-spring-3-webclient/build/
samples/client/echo_api/kotlin-jvm-okhttp/build/
samples/client/echo_api/kotlin-jvm-okhttp-multipart-json/build/
# haskell
.stack-work

View File

@@ -1260,7 +1260,7 @@ If you want to join the committee, please kindly apply by sending an email to te
| JMeter | @kannkyo (2021/01) |
| Jetbrains HTTP Client | @jlengrand (2023/01) |
| Julia | @tanmaykm (2023/01) |
| Kotlin | @karismann (2019/03) @Zomzog (2019/04) @andrewemery (2019/10) @4brunu (2019/11) @yutaka0m (2020/03) @stefankoppier (2022/06) @e5l (2024/10) @dennisameling (2026/02) |
| Kotlin | @karismann (2019/03) @Zomzog (2019/04) @andrewemery (2019/10) @4brunu (2019/11) @yutaka0m (2020/03) @stefankoppier (2022/06) @e5l (2024/10) |
| Lua | @daurnimator (2017/08) |
| N4JS | @mmews-n4 (2023/03) |
| Nim | |
@@ -1276,7 +1276,7 @@ If you want to join the committee, please kindly apply by sending an email to te
| Rust | @frol (2017/07) @farcaller (2017/08) @richardwhiuk (2019/07) @paladinzh (2020/05) @jacob-pro (2022/10) @dsteeley (2025/07) |
| Scala | @clasnake (2017/07), @shijinkui (2018/01), @ramzimaalej (2018/03), @chameleon82 (2020/03), @Bouillie (2020/04) @fish86 (2023/06) |
| Swift | @jgavris (2017/07) @ehyche (2017/08) @Edubits (2017/09) @jaz-ah (2017/09) @4brunu (2019/11) @dydus0x14 (2023/06) |
| TypeScript | @TiFu (2017/07) @taxpon (2017/07) @sebastianhaas (2017/07) @kenisteward (2017/07) @Vrolijkx (2017/09) @macjohnny (2018/01) @topce (2018/10) @akehir (2019/07) @petejohansonxo (2019/11) @amakhrov (2020/02) @davidgamero (2022/03) @mkusaka (2022/04) @joscha (2024/10) @dennisameling (2026/02) |
| TypeScript | @TiFu (2017/07) @taxpon (2017/07) @sebastianhaas (2017/07) @kenisteward (2017/07) @Vrolijkx (2017/09) @macjohnny (2018/01) @topce (2018/10) @akehir (2019/07) @petejohansonxo (2019/11) @amakhrov (2020/02) @davidgamero (2022/03) @mkusaka (2022/04) @joscha (2024/10) |
| Xojo | @Topheee (2023/04) |

View File

@@ -3,11 +3,13 @@ outputDir: samples/server/petstore/java-camel
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/java-camel-server
additionalProperties:
oas3: "true"
hideGenerationTimestamp: true
camelRestBindingMode: "auto"
performBeanValidation: true
#dateLibrary: "java8-localdatetime"
camelDataformatProperties: "json.out.disableFeatures=WRITE_DATES_AS_TIMESTAMPS"
library: "spring-boot"
withXml: true
jackson: true
camelUseDefaultValidationErrorProcessor: true

View File

@@ -1,7 +0,0 @@
generatorName: kotlin-server
outputDir: samples/server/others/kotlin-server/polymorphism-allof-and-discriminator
inputSpec: modules/openapi-generator/src/test/resources/3_1/polymorphism-allof-and-discriminator.yaml
templateDir: modules/openapi-generator/src/main/resources/kotlin-server
additionalProperties:
artifactId: kotlin-server-polymorphism-allof-and-discriminator
library: javalin6

View File

@@ -1,10 +0,0 @@
generatorName: kotlin-server
outputDir: samples/server/others/kotlin-server/polymorphism-and-discriminator-disabled-jackson-fix
inputSpec: modules/openapi-generator/src/test/resources/3_1/polymorphism-and-discriminator.yaml
templateDir: modules/openapi-generator/src/main/resources/kotlin-server
additionalProperties:
artifactId: kotlin-server-polymorphism-and-discriminator-disabled-jackson-fix
library: javalin6
# This is set to "true" by default, but we also want to test the case where it's set to false.
# See KotlinServerCodegen.java for more details about this property.
fixJacksonJsonTypeInfoInheritance: false

View File

@@ -1,8 +0,0 @@
generatorName: kotlin-server
outputDir: samples/server/others/kotlin-server/polymorphism-and-discriminator
inputSpec: modules/openapi-generator/src/test/resources/3_1/polymorphism-and-discriminator.yaml
templateDir: modules/openapi-generator/src/main/resources/kotlin-server
additionalProperties:
artifactId: kotlin-server-polymorphism-and-discriminator
library: javalin6
fixJacksonJsonTypeInfoInheritance: true

View File

@@ -1,7 +0,0 @@
generatorName: kotlin-server
outputDir: samples/server/others/kotlin-server/polymorphism
inputSpec: modules/openapi-generator/src/test/resources/3_1/polymorphism.yaml
templateDir: modules/openapi-generator/src/main/resources/kotlin-server
additionalProperties:
artifactId: kotlin-server-polymorphism
library: javalin6

View File

@@ -13,14 +13,3 @@ additionalProperties:
serializableModel: true
beanValidations: true
includeHttpRequestContext: true
schemaImplements:
Pet: com.some.pack.WithId
Category: [ com.some.pack.CategoryInterface ]
Dog: [ com.some.pack.Canine ]
schemaImplementsFields:
Pet: id
Category: [ name, id ]
Dog: [ bark, breed ]
xKotlinImplementsSkip: [ com.some.pack.WithPhotoUrls ]
xKotlinImplementsFieldsSkip:
Pet: [ photoUrls ]

View File

@@ -13,4 +13,3 @@ additionalProperties:
reactive: false
useResponseEntity: true
useFlowForArrayReturnType: false
requestMappingMode: "api_interface"

View File

@@ -1,15 +0,0 @@
generatorName: spring
outputDir: samples/server/petstore/springboot-x-implements-skip
inputSpec: modules/openapi-generator/src/test/resources/3_0/spring/petstore-with-fake-endpoints-models-for-testing-x-implements.yaml
templateDir: modules/openapi-generator/src/main/resources/JavaSpring
additionalProperties:
documentationProvider: springfox
artifactId: springboot
snapshotVersion: "true"
hideGenerationTimestamp: "true"
camelCaseDollarSign: "true"
modelNameSuffix: 'Dto'
xImplementsSkip: [ com.custompackage.InterfaceToSkip ]
schemaImplements:
Foo: [ com.custompackage.WithBar, com.custompackage.WithDefaultMethod ]
Animal: com.custompackage.WithColor

View File

@@ -10,7 +10,7 @@
- filename: "samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/ClientTest.java"
sha256: 325fdd5d7e2c97790c0fb44f712ab7b2ba022d7e1a5b0056f47b07f342682b6d
- filename: "samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/JSONTest.java"
sha256: b1b1d31e0df17f0b68cf2747a4a53879f12acb1bf2860e45385c679c1efe9894
sha256: 67941355a0a27ed9ff9318b1caa103e78b81b9aff61b594b18be5cd2bb9f6591
- filename: "samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/api/PetApiTest.java"
sha256: 8b1b8f2a2ad00ccb090873a94a5f73e328b98317d2ec715f53bd7a1accb2a023
- filename: "samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/model/PetTest.java"

View File

@@ -87,7 +87,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|resourceFolder|resource folder for generated resources| |src/main/resources|
|responseWrapper|wrap the responses in given type (Future, Callable, CompletableFuture,ListenableFuture, DeferredResult, RxObservable, RxSingle or fully qualified type)| |null|
|returnSuccessCode|Generated server returns 2xx code| |false|
|schemaImplements|Ability to supply interfaces per schema that should be implemented (serves similar purpose as vendor extension `x-implements`, but is fully decoupled from the api spec). Example: yaml `schemaImplements: {Pet: com.some.pack.WithId, Category: [com.some.pack.CategoryInterface], Dog: [com.some.pack.Canine, com.some.pack.OtherInterface]}` implements interfaces in schemas `Pet` (interface `com.some.pack.WithId`), `Category` (interface `com.some.pack.CategoryInterface`), `Dog`(interfaces `com.some.pack.Canine`, `com.some.pack.OtherInterface`)| |empty map|
|scmConnection|SCM connection in generated pom.xml| |scm:git:git@github.com:openapitools/openapi-generator.git|
|scmDeveloperConnection|SCM developer connection in generated pom.xml| |scm:git:git@github.com:openapitools/openapi-generator.git|
|scmUrl|SCM URL in generated pom.xml| |https://github.com/openapitools/openapi-generator|
@@ -119,7 +118,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useTags|use tags for creating interface and controller classnames| |false|
|virtualService|Generates the virtual service. For more details refer - https://github.com/virtualansoftware/virtualan/wiki| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
|xImplementsSkip|Ability to choose interfaces that should NOT be implemented in the models despite their presence in vendor extension `x-implements`. Takes a list of fully qualified interface names. Example: yaml `xImplementsSkip: [com.some.pack.WithPhotoUrls]` skips implementing the interface `com.some.pack.WithPhotoUrls` in any schema| |empty list|
## SUPPORTED VENDOR EXTENSIONS

View File

@@ -30,7 +30,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|featureHSTS|Avoid sending content if client already has same content, by checking ETag or LastModified properties.| |true|
|featureMetrics|Enables metrics feature.| |true|
|featureResources|Generates routes in a typed way, for both: constructing URLs and reading the parameters.| |true|
|fixJacksonJsonTypeInfoInheritance|When true (default), ensures Jackson polymorphism works correctly by: (1) always setting visible=true on @JsonTypeInfo, and (2) adding the discriminator property to child models with appropriate default values. When false, visible is only set to true if all children already define the discriminator property.| |true|
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
|interfaceOnly|Whether to generate only API interface stubs without the server files. This option is currently supported only when using jaxrs-spec library.| |false|
|library|library template (sub-template)|<dl><dt>**ktor**</dt><dd>ktor framework</dd><dt>**ktor2**</dt><dd>ktor (2.x) framework</dd><dt>**jaxrs-spec**</dt><dd>JAX-RS spec only</dd><dt>**javalin5**</dt><dd>Javalin 5</dd><dt>**javalin6**</dt><dd>Javalin 6</dd></dl>|ktor|
@@ -263,11 +262,11 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---- | --------- | ---------- |
|Simple|✓|OAS2,OAS3
|Composite|✓|OAS2,OAS3
|Polymorphism||OAS2,OAS3
|Polymorphism||OAS2,OAS3
|Union|✗|OAS3
|allOf||OAS2,OAS3
|allOf||OAS2,OAS3
|anyOf|✗|OAS3
|oneOf||OAS3
|oneOf||OAS3
|not|✗|OAS3
### Security Feature

View File

@@ -43,8 +43,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|parcelizeModels|toggle &quot;@Parcelize&quot; for generated models| |null|
|reactive|use coroutines for reactive behavior| |false|
|requestMappingMode|Where to generate the class level @RequestMapping annotation.|<dl><dt>**api_interface**</dt><dd>Generate the @RequestMapping annotation on the generated Api Interface.</dd><dt>**controller**</dt><dd>Generate the @RequestMapping annotation on the generated Api Controller Implementation.</dd><dt>**none**</dt><dd>Do not add a class level @RequestMapping annotation.</dd></dl>|controller|
|schemaImplements|A map of single interface or a list of interfaces per schema name that should be implemented (serves similar purpose as `x-kotlin-implements`, but is fully decoupled from the api spec). Example: yaml `schemaImplements: {Pet: com.some.pack.WithId, Category: [com.some.pack.CategoryInterface], Dog: [com.some.pack.Canine, com.some.pack.OtherInterface]}` implements interfaces in schemas `Pet` (interface `com.some.pack.WithId`), `Category` (interface `com.some.pack.CategoryInterface`), `Dog`(interfaces `com.some.pack.Canine`, `com.some.pack.OtherInterface`)| |empty map|
|schemaImplementsFields|A map of single field or a list of fields per schema name that should be prepended with `override` (serves similar purpose as `x-kotlin-implements-fields`, but is fully decoupled from the api spec). Example: yaml `schemaImplementsFields: {Pet: id, Category: [name, id], Dog: [bark, breed]}` marks fields to be prepended with `override` in schemas `Pet` (field `id`), `Category` (fields `name`, `id`) and `Dog` (fields `bark`, `breed`)| |empty map|
|serializableModel|boolean - toggle &quot;implements Serializable&quot; for generated models| |null|
|serverPort|configuration the port in which the sever is to run on| |8080|
|serviceImplementation|generate stub service implementations that extends service interfaces. If this is set to true service interfaces will also be generated| |false|
@@ -61,8 +59,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot &ge; 3 (use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.| |false|
|useSwaggerUI|Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies| |true|
|useTags|Whether to use tags for creating interface and controller class names| |false|
|xKotlinImplementsFieldsSkip|A list of fields per schema name that should NOT be created with `override` keyword despite their presence in vendor extension `x-kotlin-implements-fields` for the schema. Example: yaml `xKotlinImplementsFieldsSkip: Pet: [photoUrls]` skips `override` for `photoUrls` in schema `Pet`| |empty map|
|xKotlinImplementsSkip|A list of fully qualified interfaces that should NOT be implemented despite their presence in vendor extension `x-kotlin-implements`. Example: yaml `xKotlinImplementsSkip: [com.some.pack.WithPhotoUrls]` skips implementing the interface in any schema| |empty list|
## SUPPORTED VENDOR EXTENSIONS

View File

@@ -80,7 +80,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|resourceFolder|resource folder for generated resources| |src/main/resources|
|responseWrapper|wrap the responses in given type (Future, Callable, CompletableFuture,ListenableFuture, DeferredResult, RxObservable, RxSingle or fully qualified type)| |null|
|returnSuccessCode|Generated server returns 2xx code| |false|
|schemaImplements|Ability to supply interfaces per schema that should be implemented (serves similar purpose as vendor extension `x-implements`, but is fully decoupled from the api spec). Example: yaml `schemaImplements: {Pet: com.some.pack.WithId, Category: [com.some.pack.CategoryInterface], Dog: [com.some.pack.Canine, com.some.pack.OtherInterface]}` implements interfaces in schemas `Pet` (interface `com.some.pack.WithId`), `Category` (interface `com.some.pack.CategoryInterface`), `Dog`(interfaces `com.some.pack.Canine`, `com.some.pack.OtherInterface`)| |empty map|
|scmConnection|SCM connection in generated pom.xml| |scm:git:git@github.com:openapitools/openapi-generator.git|
|scmDeveloperConnection|SCM developer connection in generated pom.xml| |scm:git:git@github.com:openapitools/openapi-generator.git|
|scmUrl|SCM URL in generated pom.xml| |https://github.com/openapitools/openapi-generator|
@@ -112,7 +111,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useTags|use tags for creating interface and controller classnames| |false|
|virtualService|Generates the virtual service. For more details refer - https://github.com/virtualansoftware/virtualan/wiki| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
|xImplementsSkip|Ability to choose interfaces that should NOT be implemented in the models despite their presence in vendor extension `x-implements`. Takes a list of fully qualified interface names. Example: yaml `xImplementsSkip: [com.some.pack.WithPhotoUrls]` skips implementing the interface `com.some.pack.WithPhotoUrls` in any schema| |empty list|
## SUPPORTED VENDOR EXTENSIONS

View File

@@ -42,7 +42,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|supportsES6|Generate code that conforms to ES6.| |false|
|typescriptMajorVersion|Specify the major version of TypeScript to use in the client code. Default is 5.| |5|
|useErasableSyntax|Use erasable syntax for the generated code. This is a temporary feature and will be removed in the future.| |false|
|useInversify|Enable this to generate decorators and service identifiers for the InversifyJS inversion of control container. If you set 'deno' as 'platform', the generator will process this value as 'disable'.| |false|
|useObjectParameters|Use aggregate parameter objects as function arguments for api operations instead of passing each parameter as a separate function argument.| |false|

View File

@@ -112,10 +112,6 @@ public class CliOption {
return new CliOption(opt, description, SchemaTypeUtil.STRING_TYPE);
}
public static CliOption newString(String opt, String description, String defaultValue) {
return new CliOption(opt, description, SchemaTypeUtil.STRING_TYPE).defaultValue(String.valueOf(defaultValue));
}
@JsonIgnore
public String getOptionHelp() {
StringBuilder sb = new StringBuilder(description);

View File

@@ -94,11 +94,8 @@ import static org.openapitools.codegen.utils.OnceLogger.once;
import static org.openapitools.codegen.utils.StringUtils.*;
public class DefaultCodegen implements CodegenConfig {
private final Logger LOGGER = LoggerFactory.getLogger(DefaultCodegen.class);
public static final Pattern SPLIT_ON_SEMICOLON_OR_NEWLINE_REGEX = Pattern.compile("\\s*(;|\\r?\\n)\\s*"); // Splits on semicolon or new line, ignoring surrounding whitespace
public static FeatureSet DefaultFeatureSet;
// A cache of sanitized words. The sanitizeName() method is invoked many times with the same
@@ -193,20 +190,15 @@ public class DefaultCodegen implements CodegenConfig {
protected Map<String, String> operationIdNameMapping = new HashMap<>();
// a map to store the rules in OpenAPI Normalizer
protected Map<String, String> openapiNormalizer = new HashMap<>();
@Setter
protected String modelPackage = "", apiPackage = "";
@Setter protected String modelPackage = "", apiPackage = "";
protected String fileSuffix;
@Getter
@Setter
@Getter @Setter
protected String modelNamePrefix = "", modelNameSuffix = "";
@Getter
@Setter
@Getter @Setter
protected String apiNamePrefix = "", apiNameSuffix = "Api";
protected String testPackage = "";
@Setter
protected String filesMetadataFilename = "FILES";
@Setter
protected String versionMetadataFilename = "VERSION";
@Setter protected String filesMetadataFilename = "FILES";
@Setter protected String versionMetadataFilename = "VERSION";
/*
apiTemplateFiles are for API outputs only (controllers/handlers).
API templates may be written multiple times; APIs are grouped by tag and the file is written once per tag group.
@@ -218,8 +210,7 @@ public class DefaultCodegen implements CodegenConfig {
protected Map<String, String> apiDocTemplateFiles = new HashMap<>();
protected Map<String, String> modelDocTemplateFiles = new HashMap<>();
protected Map<String, String> reservedWordsMappings = new HashMap<>();
@Setter
protected String templateDir;
@Setter protected String templateDir;
protected String embeddedTemplateDir;
protected Map<String, Object> additionalProperties = new HashMap<>();
protected Map<String, String> serverVariables = new HashMap<>();
@@ -234,11 +225,9 @@ public class DefaultCodegen implements CodegenConfig {
protected List<CliOption> cliOptions = new ArrayList<>();
protected boolean skipOverwrite;
protected boolean removeOperationIdPrefix;
@Getter
@Setter
@Getter @Setter
protected String removeOperationIdPrefixDelimiter = "_";
@Getter
@Setter
@Getter @Setter
protected int removeOperationIdPrefixCount = 1;
protected boolean skipOperationExample;
// sort operations by default
@@ -273,17 +262,13 @@ public class DefaultCodegen implements CodegenConfig {
protected boolean supportsMixins;
protected Map<String, String> supportedLibraries = new LinkedHashMap<>();
protected String library;
@Getter
@Setter
@Getter @Setter
protected Boolean sortParamsByRequiredFlag = true;
@Getter
@Setter
@Getter @Setter
protected Boolean sortModelPropertiesByRequiredFlag = false;
@Getter
@Setter
@Getter @Setter
protected Boolean ensureUniqueParams = true;
@Getter
@Setter
@Getter @Setter
protected Boolean allowUnicodeIdentifiers = false;
protected String gitHost, gitUserId, gitRepoId, releaseNote;
protected String httpUserAgent;
@@ -294,8 +279,7 @@ public class DefaultCodegen implements CodegenConfig {
protected Map<String, String> specialCharReplacements = new LinkedHashMap<>();
// When a model is an alias for a simple type
protected Map<String, String> typeAliases = Collections.emptyMap();
@Getter
@Setter
@Getter @Setter
protected Boolean prependFormOrBodyParameters = false;
// The extension of the generated documentation files (defaults to markdown .md)
protected String docExtension;
@@ -318,18 +302,15 @@ public class DefaultCodegen implements CodegenConfig {
protected boolean removeEnumValuePrefix = false;
// Support legacy logic for evaluating discriminators
@Setter
protected boolean legacyDiscriminatorBehavior = true;
@Setter protected boolean legacyDiscriminatorBehavior = true;
// Specify what to do if the 'additionalProperties' keyword is not present in a schema.
// See CodegenConstants.java for more details.
@Setter
protected boolean disallowAdditionalPropertiesIfNotPresent = true;
@Setter protected boolean disallowAdditionalPropertiesIfNotPresent = true;
// If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.
// With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.
@Setter
protected boolean enumUnknownDefaultCase = false;
@Setter protected boolean enumUnknownDefaultCase = false;
protected String enumUnknownDefaultCaseName = "unknown_default_open_api";
// make openapi available to all methods
@@ -352,18 +333,11 @@ public class DefaultCodegen implements CodegenConfig {
protected boolean addSuffixToDuplicateOperationNicknames = true;
// Whether to automatically hardcode params that are considered Constants by OpenAPI Spec
@Setter
protected boolean autosetConstants = false;
@Setter protected boolean autosetConstants = false;
@Setter
@Getter
boolean arrayDefaultToEmpty, arrayNullableDefaultToEmpty, arrayOptionalNullableDefaultToEmpty, arrayOptionalDefaultToEmpty;
@Setter
@Getter
boolean mapDefaultToEmpty, mapNullableDefaultToEmpty, mapOptionalNullableDefaultToEmpty, mapOptionalDefaultToEmpty;
@Setter
@Getter
protected boolean defaultToEmptyContainer;
@Setter @Getter boolean arrayDefaultToEmpty, arrayNullableDefaultToEmpty, arrayOptionalNullableDefaultToEmpty, arrayOptionalDefaultToEmpty;
@Setter @Getter boolean mapDefaultToEmpty, mapNullableDefaultToEmpty, mapOptionalNullableDefaultToEmpty, mapOptionalDefaultToEmpty;
@Setter @Getter protected boolean defaultToEmptyContainer;
final List EMPTY_LIST = new ArrayList();
@@ -598,7 +572,7 @@ public class DefaultCodegen implements CodegenConfig {
? false
: model.parentModel.allVars.stream().anyMatch(p ->
p.name.equals(property.name) &&
(p.dataType.equals(property.dataType) == false || p.datatypeWithEnum.equals(property.datatypeWithEnum) == false));
(p.dataType.equals(property.dataType) == false || p.datatypeWithEnum.equals(property.datatypeWithEnum) == false));
}
/**
@@ -742,7 +716,7 @@ public class DefaultCodegen implements CodegenConfig {
for (CodegenProperty cp : model.allVars) {
// detect self import
if (cp.dataType.equalsIgnoreCase(model.classname) ||
(cp.isContainer && cp.items != null && cp.items.dataType.equalsIgnoreCase(model.classname))) {
(cp.isContainer && cp.items != null && cp.items.dataType.equalsIgnoreCase(model.classname))) {
model.imports.remove(model.classname); // remove self import
cp.isSelfReference = true;
}
@@ -784,7 +758,7 @@ public class DefaultCodegen implements CodegenConfig {
}
private void setCircularReferencesOnProperties(final String root,
final Map<String, List<CodegenProperty>> dependencyMap) {
final Map<String, List<CodegenProperty>> dependencyMap) {
dependencyMap.getOrDefault(root, new ArrayList<>())
.forEach(prop -> {
final List<String> unvisited =
@@ -797,9 +771,9 @@ public class DefaultCodegen implements CodegenConfig {
}
private boolean isCircularReference(final String root,
final Set<String> visited,
final List<String> unvisited,
final Map<String, List<CodegenProperty>> dependencyMap) {
final Set<String> visited,
final List<String> unvisited,
final Map<String, List<CodegenProperty>> dependencyMap) {
for (int i = 0; i < unvisited.size(); i++) {
final String next = unvisited.get(i);
if (!visited.contains(next)) {
@@ -1188,6 +1162,7 @@ public class DefaultCodegen implements CodegenConfig {
return escapeText(input).replace("'", "\\'");
}
/**
* Escape characters while allowing new lines
*
@@ -1231,7 +1206,7 @@ public class DefaultCodegen implements CodegenConfig {
@Override
public String escapeUnsafeCharacters(String input) {
LOGGER.warn("escapeUnsafeCharacters should be overridden in the code generator with proper logic to escape " +
"unsafe characters");
"unsafe characters");
// doing nothing by default and code generator should implement
// the logic to prevent code injection
// later we'll make this method abstract to make sure
@@ -1248,7 +1223,7 @@ public class DefaultCodegen implements CodegenConfig {
@Override
public String escapeQuotationMark(String input) {
LOGGER.warn("escapeQuotationMark should be overridden in the code generator with proper logic to escape " +
"single/double quote");
"single/double quote");
return input.replace("\"", "\\\"");
}
@@ -1826,8 +1801,7 @@ public class DefaultCodegen implements CodegenConfig {
CliOption legacyDiscriminatorBehaviorOpt = CliOption.newBoolean(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR_DESC).defaultValue(Boolean.TRUE.toString());
Map<String, String> legacyDiscriminatorBehaviorOpts = new HashMap<>();
legacyDiscriminatorBehaviorOpts.put("true", "The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.");
legacyDiscriminatorBehaviorOpts.put("false",
"The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.");
legacyDiscriminatorBehaviorOpts.put("false", "The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.");
legacyDiscriminatorBehaviorOpt.setEnum(legacyDiscriminatorBehaviorOpts);
cliOptions.add(legacyDiscriminatorBehaviorOpt);
@@ -2311,6 +2285,7 @@ public class DefaultCodegen implements CodegenConfig {
}
protected Schema<?> getSchemaAdditionalProperties(Schema schema) {
Schema<?> inner = ModelUtils.getAdditionalProperties(schema);
if (inner == null) {
@@ -2384,7 +2359,7 @@ public class DefaultCodegen implements CodegenConfig {
return ModelUtils.unaliasSchema(this.openAPI, schema, schemaMapping);
}
private List<Map<String, Object>> unaliasExamples(Map<String, Example> examples) {
private List<Map<String, Object>> unaliasExamples(Map<String, Example> examples){
return ExamplesUtils.unaliasExamples(this.openAPI, examples);
}
@@ -2656,7 +2631,6 @@ public class DefaultCodegen implements CodegenConfig {
}
private static class NamedSchema {
private NamedSchema(String name, Schema s, boolean required, boolean schemaIsFromAdditionalProperties) {
this.name = name;
this.schema = s;
@@ -2671,15 +2645,13 @@ public class DefaultCodegen implements CodegenConfig {
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
NamedSchema that = (NamedSchema) o;
return Objects.equals(required, that.required) &&
Objects.equals(name, that.name) &&
Objects.equals(schema, that.schema) &&
Objects.equals(schemaIsFromAdditionalProperties, that.schemaIsFromAdditionalProperties);
Objects.equals(name, that.name) &&
Objects.equals(schema, that.schema) &&
Objects.equals(schemaIsFromAdditionalProperties, that.schemaIsFromAdditionalProperties);
}
@Override
@@ -2701,7 +2673,7 @@ public class DefaultCodegen implements CodegenConfig {
if (composed.getProperties() != null && !composed.getProperties().isEmpty()) {
if (composed.getOneOf() != null && !composed.getOneOf().isEmpty()) {
LOGGER.warn("'oneOf' is intended to include only the additional optional OAS extension discriminator object. " +
"For more details, see https://json-schema.org/draft/2019-09/json-schema-core.html#rfc.section.9.2.1.3 and the OAS section on 'Composition and Inheritance'.");
"For more details, see https://json-schema.org/draft/2019-09/json-schema-core.html#rfc.section.9.2.1.3 and the OAS section on 'Composition and Inheritance'.");
}
addVars(m, unaliasPropertySchema(composed.getProperties()), composed.getRequired(), null, null);
}
@@ -3096,7 +3068,7 @@ public class DefaultCodegen implements CodegenConfig {
m.getVendorExtensions().putAll(schema.getExtensions());
}
m.isAlias = (typeAliases.containsKey(name)
|| isAliasOfSimpleTypes(schema)); // check if the unaliased schema is an alias of simple OAS types
|| isAliasOfSimpleTypes(schema)); // check if the unaliased schema is an alias of simple OAS types
m.setDiscriminator(createDiscriminator(name, schema));
if (schema.getDeprecated() != null) {
@@ -3467,7 +3439,7 @@ public class DefaultCodegen implements CodegenConfig {
}
if (discriminatorsPropNames.size() > 1) {
once(LOGGER).warn("The oneOf schemas have conflicting discriminator property names. " +
"oneOf schemas must have the same property name, but found " + String.join(", ", discriminatorsPropNames));
"oneOf schemas must have the same property name, but found " + String.join(", ", discriminatorsPropNames));
}
if (foundDisc != null && (hasDiscriminatorCnt + hasNullTypeCnt) == composedSchema.getOneOf().size() && discriminatorsPropNames.size() == 1) {
disc.setPropertyName(foundDisc.getPropertyName());
@@ -3496,7 +3468,7 @@ public class DefaultCodegen implements CodegenConfig {
}
if (discriminatorsPropNames.size() > 1) {
once(LOGGER).warn("The anyOf schemas have conflicting discriminator property names. " +
"anyOf schemas must have the same property name, but found " + String.join(", ", discriminatorsPropNames));
"anyOf schemas must have the same property name, but found " + String.join(", ", discriminatorsPropNames));
}
if (foundDisc != null && (hasDiscriminatorCnt + hasNullTypeCnt) == composedSchema.getAnyOf().size() && discriminatorsPropNames.size() == 1) {
disc.setPropertyName(foundDisc.getPropertyName());
@@ -3695,7 +3667,7 @@ public class DefaultCodegen implements CodegenConfig {
boolean matched = false;
for (MappedModel uniqueDescendant : uniqueDescendants) {
if (uniqueDescendant.getMappingName().equals(otherDescendant.getMappingName())
|| (uniqueDescendant.getModelName().equals(otherDescendant.getModelName()))) {
|| (uniqueDescendant.getModelName().equals(otherDescendant.getModelName()))) {
matched = true;
break;
}
@@ -3893,9 +3865,9 @@ public class DefaultCodegen implements CodegenConfig {
}
property.isNullable = property.isNullable ||
!(ModelUtils.isComposedSchema(p)) ||
p.getAllOf() == null ||
p.getAllOf().size() == 0;
!(ModelUtils.isComposedSchema(p)) ||
p.getAllOf() == null ||
p.getAllOf().size() == 0;
if (languageSpecificPrimitives.contains(property.dataType)) {
property.isPrimitiveType = true;
}
@@ -3971,6 +3943,7 @@ public class DefaultCodegen implements CodegenConfig {
return fromProperty(name, p, required, false);
}
/**
* TODO remove this in 7.0.0 as a breaking change
* This method was kept when required was added to the fromProperty signature
@@ -4151,7 +4124,7 @@ public class DefaultCodegen implements CodegenConfig {
if (referencedSchema.getNullable() != null) {
property.isNullable = referencedSchema.getNullable();
} else if (referencedSchema.getExtensions() != null &&
referencedSchema.getExtensions().containsKey(X_NULLABLE)) {
referencedSchema.getExtensions().containsKey(X_NULLABLE)) {
property.isNullable = (Boolean) referencedSchema.getExtensions().get(X_NULLABLE);
}
@@ -4235,9 +4208,9 @@ public class DefaultCodegen implements CodegenConfig {
}
boolean isAnyTypeWithNothingElseSet = (ModelUtils.isAnyType(p) &&
(p.getProperties() == null || p.getProperties().isEmpty()) &&
!ModelUtils.isComposedSchema(p) &&
p.getAdditionalProperties() == null && p.getNot() == null && p.getEnum() == null);
(p.getProperties() == null || p.getProperties().isEmpty()) &&
!ModelUtils.isComposedSchema(p) &&
p.getAdditionalProperties() == null && p.getNot() == null && p.getEnum() == null);
if (!ModelUtils.isArraySchema(p) && !ModelUtils.isMapSchema(p) && !ModelUtils.isFreeFormObject(p, openAPI) && !isAnyTypeWithNothingElseSet) {
/* schemas that are not Array, not ModelUtils.isMapSchema, not isFreeFormObject, not AnyType with nothing else set
@@ -4316,7 +4289,7 @@ public class DefaultCodegen implements CodegenConfig {
* update container's default to empty container according rules provided by the user.
*
* @param cp codegen property
* @param p schema
* @param p schema
*/
void updateDefaultToEmptyContainer(CodegenProperty cp, Schema p) {
if (cp.isArray) {
@@ -4358,7 +4331,7 @@ public class DefaultCodegen implements CodegenConfig {
void parseDefaultToEmptyContainer(String input) {
String[] inputs = ((String) input).split("[|]");
String containerType;
for (String rule : inputs) {
for (String rule: inputs) {
if (StringUtils.isEmpty(rule)) {
LOGGER.error("updateDefaultToEmptyContainer: Skipped empty input in `{}`.", input);
continue;
@@ -4383,7 +4356,7 @@ public class DefaultCodegen implements CodegenConfig {
LOGGER.error("Skipped invalid container type `{}` in `{}`.", containerType, input);
}
} else if (rule.endsWith("?")) { // optional
containerType = rule.substring(0, rule.length() - 1);
containerType = rule.substring(0, rule.length()-1);
if ("array".equalsIgnoreCase(containerType)) {
arrayOptionalDefaultToEmpty = true;
} else if ("map".equalsIgnoreCase(containerType)) {
@@ -4493,7 +4466,7 @@ public class DefaultCodegen implements CodegenConfig {
protected CodegenProperty getMostInnerItems(CodegenProperty property) {
CodegenProperty currentProperty = property;
while (currentProperty != null && (Boolean.TRUE.equals(currentProperty.isMap)
|| Boolean.TRUE.equals(currentProperty.isArray)) && currentProperty.items != null) {
|| Boolean.TRUE.equals(currentProperty.isArray)) && currentProperty.items != null) {
currentProperty = currentProperty.items;
}
return currentProperty;
@@ -4513,7 +4486,7 @@ public class DefaultCodegen implements CodegenConfig {
protected void updateDataTypeWithEnumForArray(CodegenProperty property) {
CodegenProperty baseItem = property.items;
while (baseItem != null && (Boolean.TRUE.equals(baseItem.isMap)
|| Boolean.TRUE.equals(baseItem.isArray))) {
|| Boolean.TRUE.equals(baseItem.isArray))) {
baseItem = baseItem.items;
}
if (baseItem != null) {
@@ -4541,7 +4514,7 @@ public class DefaultCodegen implements CodegenConfig {
protected void updateDataTypeWithEnumForMap(CodegenProperty property) {
CodegenProperty baseItem = property.items;
while (baseItem != null && (Boolean.TRUE.equals(baseItem.isMap)
|| Boolean.TRUE.equals(baseItem.isArray))) {
|| Boolean.TRUE.equals(baseItem.isArray))) {
baseItem = baseItem.items;
}
@@ -4602,9 +4575,9 @@ public class DefaultCodegen implements CodegenConfig {
* @param methodResponse the default ApiResponse for the endpoint
*/
protected void handleMethodResponse(Operation operation,
Map<String, Schema> schemas,
CodegenOperation op,
ApiResponse methodResponse) {
Map<String, Schema> schemas,
CodegenOperation op,
ApiResponse methodResponse) {
handleMethodResponse(operation, schemas, op, methodResponse, Collections.emptyMap());
}
@@ -4618,10 +4591,10 @@ public class DefaultCodegen implements CodegenConfig {
* @param schemaMappings mappings of external types to be omitted by unaliasing
*/
protected void handleMethodResponse(Operation operation,
Map<String, Schema> schemas,
CodegenOperation op,
ApiResponse methodResponse,
Map<String, String> schemaMappings) {
Map<String, Schema> schemas,
CodegenOperation op,
ApiResponse methodResponse,
Map<String, String> schemaMappings) {
ApiResponse response = ModelUtils.getReferencedApiResponse(openAPI, methodResponse);
Schema responseSchema = unaliasSchema(ModelUtils.getSchemaFromResponse(openAPI, response));
@@ -4690,9 +4663,9 @@ public class DefaultCodegen implements CodegenConfig {
*/
@Override
public CodegenOperation fromOperation(String path,
String httpMethod,
Operation operation,
List<Server> servers) {
String httpMethod,
Operation operation,
List<Server> servers) {
LOGGER.debug("fromOperation => operation: {}", operation);
if (operation == null)
throw new RuntimeException("operation cannot be null in fromOperation");
@@ -4760,8 +4733,8 @@ public class DefaultCodegen implements CodegenConfig {
r.setContent(getContent(response.getContent(), imports, mediaTypeSchemaSuffix));
if (r.baseType != null &&
!defaultIncludes.contains(r.baseType) &&
!languageSpecificPrimitives.contains(r.baseType)) {
!defaultIncludes.contains(r.baseType) &&
!languageSpecificPrimitives.contains(r.baseType)) {
imports.add(r.baseType);
}
@@ -4783,14 +4756,14 @@ public class DefaultCodegen implements CodegenConfig {
// check if any 4xx or 5xx response has an error response object defined
if ((Boolean.TRUE.equals(r.is4xx) || Boolean.TRUE.equals(r.is5xx)) &&
Boolean.FALSE.equals(r.primitiveType) && Boolean.FALSE.equals(r.simpleType)) {
Boolean.FALSE.equals(r.primitiveType) && Boolean.FALSE.equals(r.simpleType)) {
op.hasErrorResponseObject = Boolean.TRUE;
}
}
// check if the operation can both return a 2xx response with a body and without
if (op.responses.stream().anyMatch(response -> response.is2xx && response.dataType != null) &&
op.responses.stream().anyMatch(response -> response.is2xx && response.dataType == null)) {
op.responses.stream().anyMatch(response -> response.is2xx && response.dataType == null)) {
op.isResponseOptional = Boolean.TRUE;
}
@@ -4863,8 +4836,8 @@ public class DefaultCodegen implements CodegenConfig {
contentType = contentType.toLowerCase(Locale.ROOT);
}
if (contentType != null &&
((!(this instanceof RustAxumServerCodegen) && contentType.startsWith("application/x-www-form-urlencoded")) ||
contentType.startsWith("multipart"))) {
((!(this instanceof RustAxumServerCodegen) && contentType.startsWith("application/x-www-form-urlencoded")) ||
contentType.startsWith("multipart"))) {
// process form parameters
formParams = fromRequestBodyToFormParameters(requestBody, imports);
op.isMultipart = contentType.startsWith("multipart");
@@ -5054,23 +5027,23 @@ public class DefaultCodegen implements CodegenConfig {
r.code = responseCode;
switch (r.code.charAt(0)) {
case '1':
r.is1xx = true;
break;
case '2':
r.is2xx = true;
break;
case '3':
r.is3xx = true;
break;
case '4':
r.is4xx = true;
break;
case '5':
r.is5xx = true;
break;
default:
throw new RuntimeException("Invalid response code " + responseCode);
case '1':
r.is1xx = true;
break;
case '2':
r.is2xx = true;
break;
case '3':
r.is3xx = true;
break;
case '4':
r.is4xx = true;
break;
case '5':
r.is5xx = true;
break;
default:
throw new RuntimeException("Invalid response code " + responseCode);
}
}
@@ -5300,6 +5273,7 @@ public class DefaultCodegen implements CodegenConfig {
LOGGER.debug("debugging codegenParameter return: {}", codegenParameter);
}
private void updateParameterForMap(CodegenParameter codegenParameter, Schema parameterSchema, Set<String> imports) {
CodegenProperty codegenProperty = fromProperty("inner", ModelUtils.getAdditionalProperties(parameterSchema), false);
codegenParameter.items = codegenProperty;
@@ -5879,7 +5853,7 @@ public class DefaultCodegen implements CodegenConfig {
*/
protected boolean needToImport(String type) {
return StringUtils.isNotBlank(type) && !defaultIncludes.contains(type)
&& !languageSpecificPrimitives.contains(type);
&& !languageSpecificPrimitives.contains(type);
}
@SuppressWarnings("static-method")
@@ -6088,7 +6062,7 @@ public class DefaultCodegen implements CodegenConfig {
}
protected void addVars(CodegenModel m, Map<String, Schema> properties, List<String> required,
Map<String, Schema> allProperties, List<String> allRequired) {
Map<String, Schema> allProperties, List<String> allRequired) {
m.hasRequired = false;
m.hasReadOnly = false;
@@ -6291,7 +6265,7 @@ public class DefaultCodegen implements CodegenConfig {
// allOf with a single item
if (schema.getAllOf() != null && schema.getAllOf().size() == 1
&& schema.getAllOf().get(0) instanceof Schema) {
&& schema.getAllOf().get(0) instanceof Schema) {
schema = unaliasSchema((Schema) schema.getAllOf().get(0));
schema = ModelUtils.getReferencedSchema(this.openAPI, schema);
}
@@ -7066,6 +7040,7 @@ public class DefaultCodegen implements CodegenConfig {
return result;
}
/**
* reads propertyKey from additionalProperties, converts it to a boolean and
* writes it back to additionalProperties to be usable as a boolean in
@@ -7140,69 +7115,6 @@ public class DefaultCodegen implements CodegenConfig {
this.ignoreFilePathOverride = ignoreFileOverride;
}
public List<String> getPropertyAsStringList(String propertyKey) {
final Object value = additionalProperties.get(propertyKey);
return getObjectAsStringList(value);
}
public static List<String> getObjectAsStringList(Object value) {
if (value instanceof List) {
List<?> list = (List<?>) value;
List<String> stringList = new ArrayList<>();
for (Object item : list) {
if (item != null) {
stringList.add(item.toString());
}
}
return stringList;
} else if (value instanceof String) {
return Collections.singletonList((String) value);
}
return Collections.emptyList();
}
public Map<String, String> getPropertyAsStringMap(String propertyKey) {
final Object value = additionalProperties.get(propertyKey);
return getObjectAsStringMap(value);
}
public static Map<String, String> getObjectAsStringMap(Object value) {
if (value instanceof Map) {
Map<?, ?> rawMap = (Map<?, ?>) value;
Map<String, String> stringMap = new HashMap<>();
for (Entry<?, ?> entry : rawMap.entrySet()) {
stringMap.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
}
return stringMap;
}
return Collections.emptyMap();
}
public Map<String, List<String>> getPropertyAsStringListMap(String propertyKey) {
final Object value = additionalProperties.get(propertyKey);
return getObjectAsStringListMap(value);
}
public static Map<String, List<String>> getObjectAsStringListMap(Object value) {
if (value instanceof Map) {
Map<?, ?> rawMap = (Map<?, ?>) value;
Map<String, List<String>> stringMap = new HashMap<>();
for (Entry<?, ?> entry : rawMap.entrySet()) {
Object entryValue = entry.getValue();
if (entryValue instanceof List) {
List<String> stringList = ((List<?>) entryValue).stream()
.map(String::valueOf)
.collect(Collectors.toList());
stringMap.put(String.valueOf(entry.getKey()), stringList);
} else {
stringMap.put(String.valueOf(entry.getKey()), Collections.singletonList(String.valueOf(entryValue)));
}
}
return stringMap;
}
return Collections.emptyMap();
}
public boolean convertPropertyToBoolean(String propertyKey) {
final Object booleanValue = additionalProperties.get(propertyKey);
boolean result = Boolean.FALSE;
@@ -7306,8 +7218,8 @@ public class DefaultCodegen implements CodegenConfig {
for (String consume : consumesInfo) {
if (consume != null &&
(consume.toLowerCase(Locale.ROOT).startsWith("application/x-www-form-urlencoded") ||
consume.toLowerCase(Locale.ROOT).startsWith("multipart"))) {
(consume.toLowerCase(Locale.ROOT).startsWith("application/x-www-form-urlencoded") ||
consume.toLowerCase(Locale.ROOT).startsWith("multipart"))) {
return true;
}
}
@@ -7426,7 +7338,7 @@ public class DefaultCodegen implements CodegenConfig {
Schema original = null;
// check if it's allOf (only 1 sub schema) with or without default/nullable/etc set in the top level
if (ModelUtils.isAllOf(schema) && schema.getAllOf().size() == 1 &&
(ModelUtils.getType(schema) == null || "object".equals(ModelUtils.getType(schema)))) {
(ModelUtils.getType(schema) == null || "object".equals(ModelUtils.getType(schema)))) {
if (schema.getAllOf().get(0) instanceof Schema) {
original = schema;
schema = (Schema) schema.getAllOf().get(0);
@@ -7718,9 +7630,9 @@ public class DefaultCodegen implements CodegenConfig {
codegenModelDescription = codegenModel.description;
} else {
LOGGER.warn("The following schema has undefined (null) baseType. " +
"It could be due to form parameter defined in OpenAPI v2 spec with incorrect consumes. " +
"A correct 'consumes' for form parameters should be " +
"'application/x-www-form-urlencoded' or 'multipart/?'");
"It could be due to form parameter defined in OpenAPI v2 spec with incorrect consumes. " +
"A correct 'consumes' for form parameters should be " +
"'application/x-www-form-urlencoded' or 'multipart/?'");
LOGGER.warn("schema: {}", schema);
LOGGER.warn("codegenModel is null. Default to UNKNOWN_BASE_TYPE");
codegenModelName = "UNKNOWN_BASE_TYPE";
@@ -7784,6 +7696,7 @@ public class DefaultCodegen implements CodegenConfig {
innerCp = innerCp.items;
}
if (StringUtils.isEmpty(bodyParameterName)) {
codegenParameter.baseName = "request_body";
} else {
@@ -8078,7 +7991,7 @@ public class DefaultCodegen implements CodegenConfig {
Schema original = null;
// check if it's allOf (only 1 sub schema) with or without default/nullable/etc set in the top level
if (ModelUtils.isAllOf(schema) && schema.getAllOf().size() == 1 &&
(ModelUtils.getType(schema) == null || "object".equals(ModelUtils.getType(schema)))) {
(ModelUtils.getType(schema) == null || "object".equals(ModelUtils.getType(schema)))) {
if (schema.getAllOf().get(0) instanceof Schema) {
original = schema;
schema = (Schema) schema.getAllOf().get(0);
@@ -8466,7 +8379,7 @@ public class DefaultCodegen implements CodegenConfig {
int exitValue = p.exitValue();
if (exitValue != 0) {
try (InputStreamReader inputStreamReader = new InputStreamReader(p.getErrorStream(), StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(inputStreamReader)) {
BufferedReader br = new BufferedReader(inputStreamReader)) {
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
@@ -8635,7 +8548,6 @@ public class DefaultCodegen implements CodegenConfig {
*/
@Getter
private static class SanitizeNameOptions {
public SanitizeNameOptions(String name, String removeCharRegEx, List<String> exceptions) {
this.name = name;
this.removeCharRegEx = removeCharRegEx;
@@ -8652,14 +8564,12 @@ public class DefaultCodegen implements CodegenConfig {
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SanitizeNameOptions that = (SanitizeNameOptions) o;
return Objects.equals(getName(), that.getName()) &&
Objects.equals(getRemoveCharRegEx(), that.getRemoveCharRegEx()) &&
Objects.equals(getExceptions(), that.getExceptions());
Objects.equals(getRemoveCharRegEx(), that.getRemoveCharRegEx()) &&
Objects.equals(getExceptions(), that.getExceptions());
}
@Override
@@ -8765,7 +8675,7 @@ public class DefaultCodegen implements CodegenConfig {
i += 1;
if (dataTypeSet.contains(cp.dataType)
|| (isTypeErasedGenerics() && dataTypeSet.contains(cp.baseType))) {
|| (isTypeErasedGenerics() && dataTypeSet.contains(cp.baseType))) {
// add "x-duplicated-data-type" to indicate if the (base) dataType already occurs before
// in other sub-schemas of allOf/anyOf/oneOf
cp.vendorExtensions.putIfAbsent("x-duplicated-data-type", true);

View File

@@ -56,7 +56,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.lang.model.SourceVersion;
import java.io.File;
import java.time.LocalDate;
import java.time.ZoneId;
@@ -64,7 +63,6 @@ import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -92,8 +90,6 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
public static final String BOOLEAN_GETTER_PREFIX = "booleanGetterPrefix";
public static final String IGNORE_ANYOF_IN_ENUM = "ignoreAnyOfInEnum";
public static final String ADDITIONAL_MODEL_TYPE_ANNOTATIONS = "additionalModelTypeAnnotations";
public static final String X_IMPLEMENTS_SKIP = "xImplementsSkip";
public static final String SCHEMA_IMPLEMENTS = "schemaImplements";
public static final String ADDITIONAL_ONE_OF_TYPE_ANNOTATIONS = "additionalOneOfTypeAnnotations";
public static final String ADDITIONAL_ENUM_TYPE_ANNOTATIONS = "additionalEnumTypeAnnotations";
public static final String DISCRIMINATOR_CASE_SENSITIVE = "discriminatorCaseSensitive";
@@ -182,12 +178,6 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
@Setter protected boolean parentOverridden = false;
@Getter @Setter
protected List<String> additionalModelTypeAnnotations = new LinkedList<>();
@Getter
@Setter
protected List<String> xImplementsSkip = new ArrayList<>();
@Getter
@Setter
protected Map<String, List<String>> schemaImplements = new HashMap<>();
protected Map<String, Boolean> lombokAnnotations = null;
@Getter @Setter
protected List<String> additionalOneOfTypeAnnotations = new LinkedList<>();
@@ -460,12 +450,6 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
convertPropertyToTypeAndWriteBack(ADDITIONAL_ENUM_TYPE_ANNOTATIONS,
annotations -> Arrays.asList(annotations.split(";")),
this::setAdditionalEnumTypeAnnotations);
if (additionalProperties.containsKey(X_IMPLEMENTS_SKIP)) {
this.setXImplementsSkip(getPropertyAsStringList(X_IMPLEMENTS_SKIP));
}
if (additionalProperties.containsKey(SCHEMA_IMPLEMENTS)) {
this.setSchemaImplements(getPropertyAsStringListMap(SCHEMA_IMPLEMENTS));
}
if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
this.setInvokerPackage((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE));
@@ -2014,63 +1998,13 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
listIterator.add(newImportMap);
}
}
// make sure the x-implements is always a List and always at least empty
// add x-implements for serializable to all models
for (ModelMap mo : objs.getModels()) {
CodegenModel cm = mo.getModel();
if (cm.getVendorExtensions().containsKey(X_IMPLEMENTS)) {
List<String> xImplements = getObjectAsStringList(cm.getVendorExtensions().get(X_IMPLEMENTS));
cm.getVendorExtensions().replace(X_IMPLEMENTS, xImplements);
} else {
cm.getVendorExtensions().put(X_IMPLEMENTS, new ArrayList<String>());
}
}
// skip interfaces predefined in open api spec in x-implements via additional property xImplementsSkip
if (!this.xImplementsSkip.isEmpty()) {
for (ModelMap mo : objs.getModels()) {
CodegenModel cm = mo.getModel();
if (!getObjectAsStringList(cm.getVendorExtensions().get(X_IMPLEMENTS)).isEmpty()) {
List<String> xImplementsInModelOriginal = getObjectAsStringList(cm.getVendorExtensions().get(X_IMPLEMENTS));
List<String> xImplementsInModelSkipped = xImplementsInModelOriginal
.stream()
.filter(o -> this.xImplementsSkip.contains(o))
.collect(Collectors.toList());
if (!xImplementsInModelSkipped.isEmpty()) {
LOGGER.info("Following interfaces configured via config option '{}' will be skipped for model {}: {}", X_IMPLEMENTS_SKIP, cm.classname, xImplementsInModelSkipped);
}
List<String> xImplementsInModelProcessed = xImplementsInModelOriginal.stream()
.filter(Predicate.not(xImplementsInModelSkipped::contains))
.collect(Collectors.toList());
// implement only the non-skipped interfaces
cm.getVendorExtensions().replace(X_IMPLEMENTS, xImplementsInModelProcessed);
}
}
}
// add interfaces defined outside of open api spec
if (!this.schemaImplements.isEmpty()) {
for (ModelMap mo : objs.getModels()) {
CodegenModel cm = mo.getModel();
if (this.schemaImplements.containsKey(cm.getSchemaName())) {
LOGGER.info("Adding interface(s) {} configured via config option '{}' to model {}", this.schemaImplements.get(cm.getSchemaName()), SCHEMA_IMPLEMENTS, cm.classname);
List<String> xImplementsInModel = getObjectAsStringList(cm.getVendorExtensions().get(X_IMPLEMENTS));
List<String> schemaImplements = this.schemaImplements.get(cm.getSchemaName());
List<String> combinedSchemaImplements = Stream.concat(xImplementsInModel.stream(), schemaImplements.stream())
.collect(Collectors.toList());
// Add all the interfaces combined
cm.getVendorExtensions().replace(X_IMPLEMENTS, combinedSchemaImplements);
}
}
}
// add Serializable to x-implements to all models if configured
if (this.serializableModel) {
for (ModelMap mo : objs.getModels()) {
CodegenModel cm = mo.getModel();
List<String> xImplements = new ArrayList<>(getObjectAsStringList(cm.getVendorExtensions().get(X_IMPLEMENTS)));
if (!xImplements.contains("Serializable")) {
xImplements.add("Serializable");
}
cm.getVendorExtensions().replace(X_IMPLEMENTS, xImplements);
if (this.serializableModel) {
cm.getVendorExtensions().putIfAbsent(X_IMPLEMENTS, new ArrayList<String>());
((ArrayList<String>) cm.getVendorExtensions().get(X_IMPLEMENTS)).add("Serializable");
}
}

View File

@@ -56,10 +56,6 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
public static final String JAVAX_PACKAGE = "javaxPackage";
public static final String USE_JAKARTA_EE = "useJakartaEe";
public static final String SCHEMA_IMPLEMENTS = "schemaImplements";
public static final String SCHEMA_IMPLEMENTS_FIELDS = "schemaImplementsFields";
public static final String X_KOTLIN_IMPLEMENTS_SKIP = "xKotlinImplementsSkip";
public static final String X_KOTLIN_IMPLEMENTS_FIELDS_SKIP = "xKotlinImplementsFieldsSkip";
private final Logger LOGGER = LoggerFactory.getLogger(AbstractKotlinCodegen.class);
@@ -92,18 +88,6 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
private final Map<String, String> schemaKeyToModelNameCache = new HashMap<>();
@Getter @Setter
protected List<String> additionalModelTypeAnnotations = new LinkedList<>();
@Getter
@Setter
protected Map<String, List<String>> schemaImplements = new HashMap<>();
@Getter
@Setter
protected Map<String, List<String>> schemaImplementsFields = new HashMap<>();
@Getter
@Setter
protected List<String> xKotlinImplementsSkip = new ArrayList<>();
@Getter
@Setter
protected Map<String, List<String>> xKotlinImplementsFieldsSkip = new HashMap<>();
public AbstractKotlinCodegen() {
super();
@@ -529,19 +513,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
if (additionalProperties.containsKey(ADDITIONAL_MODEL_TYPE_ANNOTATIONS)) {
String additionalAnnotationsList = additionalProperties.get(ADDITIONAL_MODEL_TYPE_ANNOTATIONS).toString();
this.setAdditionalModelTypeAnnotations(Arrays.asList(SPLIT_ON_SEMICOLON_OR_NEWLINE_REGEX.split(additionalAnnotationsList.trim())));
}
if (additionalProperties.containsKey(SCHEMA_IMPLEMENTS)) {
this.setSchemaImplements(getPropertyAsStringListMap(SCHEMA_IMPLEMENTS));
}
if (additionalProperties.containsKey(SCHEMA_IMPLEMENTS_FIELDS)) {
this.setSchemaImplementsFields(getPropertyAsStringListMap(SCHEMA_IMPLEMENTS_FIELDS));
}
if (additionalProperties.containsKey(X_KOTLIN_IMPLEMENTS_SKIP)) {
this.setXKotlinImplementsSkip(getPropertyAsStringList(X_KOTLIN_IMPLEMENTS_SKIP));
}
if (additionalProperties.containsKey(X_KOTLIN_IMPLEMENTS_FIELDS_SKIP)) {
this.setXKotlinImplementsFieldsSkip(getPropertyAsStringListMap(X_KOTLIN_IMPLEMENTS_FIELDS_SKIP));
this.setAdditionalModelTypeAnnotations(Arrays.asList(additionalAnnotationsList.trim().split("\\s*(;|\\r?\\n)\\s*")));
}
additionalProperties.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, getSortParamsByRequiredFlag());
@@ -867,52 +839,16 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
@Override
public CodegenModel fromModel(String name, Schema schema) {
CodegenModel m = super.fromModel(name, schema);
m.getVendorExtensions().putIfAbsent(VendorExtension.X_KOTLIN_IMPLEMENTS.getName(), List.of());
List<String> schemaImplementedInterfacesClasses = this.getSchemaImplements().getOrDefault(m.getSchemaName(), List.of());
List<String> schemaImplementedInterfacesFields = this.getSchemaImplementsFields().getOrDefault(m.getSchemaName(), List.of());
List<String> vendorExtensionImplementedInterfacesClasses = (List<String>) m.getVendorExtensions().get(VendorExtension.X_KOTLIN_IMPLEMENTS.getName());
List<String> interfacesToSkip = this.getXKotlinImplementsSkip().stream()
.filter(vendorExtensionImplementedInterfacesClasses::contains)
.collect(Collectors.toList());
if (!interfacesToSkip.isEmpty()) {
LOGGER.info("Interface(s) {} in model {} are skipped from being marked as implemented via config option '{}'.",
interfacesToSkip, name, X_KOTLIN_IMPLEMENTS_SKIP);
}
List<String> vendorExtensionImplementedInterfacesClassesFiltered = vendorExtensionImplementedInterfacesClasses.stream()
.filter(interfaceName -> !interfacesToSkip.contains(interfaceName))
.collect(Collectors.toList());
List<String> vendorExtensionImplementedInterfacesFields = Optional.ofNullable((List<String>) m.getVendorExtensions().get(VendorExtension.X_KOTLIN_IMPLEMENTS_FIELDS.getName()))
List<String> implementedInterfacesClasses = (List<String>) m.getVendorExtensions().getOrDefault(VendorExtension.X_KOTLIN_IMPLEMENTS.getName(), List.of());
List<String> implementedInterfacesFields = Optional.ofNullable((List<String>) m.getVendorExtensions().get(VendorExtension.X_KOTLIN_IMPLEMENTS_FIELDS.getName()))
.map(xKotlinImplementsFields -> {
if (vendorExtensionImplementedInterfacesClassesFiltered.isEmpty() && !xKotlinImplementsFields.isEmpty()) {
if (implementedInterfacesClasses.isEmpty() && !xKotlinImplementsFields.isEmpty()) {
LOGGER.warn("Annotating {} with {} without {} is not supported. {} will be ignored.",
name, VendorExtension.X_KOTLIN_IMPLEMENTS_FIELDS.getName(), VendorExtension.X_KOTLIN_IMPLEMENTS.getName(),
VendorExtension.X_KOTLIN_IMPLEMENTS_FIELDS.getName());
}
return xKotlinImplementsFields;
}).orElse(List.of());
List<String> fieldsToSkip = this.getXKotlinImplementsFieldsSkip().getOrDefault(m.getSchemaName(), List.of())
.stream()
.filter(vendorExtensionImplementedInterfacesFields::contains)
.collect(Collectors.toList());
if (!fieldsToSkip.isEmpty()) {
LOGGER.info("Field(s) {} in model {} are skipped from being marked as inherited via config option '{}'.",
fieldsToSkip, name, X_KOTLIN_IMPLEMENTS_FIELDS_SKIP);
}
List<String> vendorExtensionImplementedInterfacesFieldsFiltered = vendorExtensionImplementedInterfacesFields.stream()
.filter(interfaceName -> !fieldsToSkip.contains(interfaceName))
.collect(Collectors.toList());
List<String> combinedImplementedInterfacesClasses = Stream.concat(vendorExtensionImplementedInterfacesClassesFiltered.stream(), schemaImplementedInterfacesClasses.stream())
.distinct()
.sorted()
.collect(Collectors.toList());
List<String> combinedImplementedInterfacesFields = Stream.concat(vendorExtensionImplementedInterfacesFieldsFiltered.stream(), schemaImplementedInterfacesFields.stream())
.distinct()
.collect(Collectors.toList());
if (serializableModel && !combinedImplementedInterfacesClasses.contains("java.io.Serializable")) {
combinedImplementedInterfacesClasses.add("java.io.Serializable");
}
m.getVendorExtensions().replace(VendorExtension.X_KOTLIN_IMPLEMENTS.getName(), combinedImplementedInterfacesClasses);
LOGGER.info("Model {} implements interface(s): {}", name, combinedImplementedInterfacesClasses);
m.optionalVars = m.optionalVars.stream().distinct().collect(Collectors.toList());
// Update allVars/requiredVars/optionalVars with isInherited
// Each of these lists contains elements that are similar, but they are all cloned
@@ -929,7 +865,7 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
Stream.of(m.requiredVars, m.optionalVars)
.flatMap(List::stream)
.filter(p -> allVarsMap.containsKey(p.baseName)
|| combinedImplementedInterfacesFields.contains(p.baseName)
|| implementedInterfacesFields.contains(p.baseName)
)
.forEach(p -> p.isInherited = true);
return m;

View File

@@ -72,7 +72,7 @@ public class JavaCamelServerCodegen extends SpringCodegen implements BeanValidat
templateDir = "java-camel-server";
addCliOptions();
artifactId = "openapi-camel";
annotationLibrary = AnnotationLibrary.SWAGGER2;
super.library = "";
}
@Override

View File

@@ -25,7 +25,6 @@ import org.openapitools.codegen.*;
import org.openapitools.codegen.languages.features.BeanValidationFeatures;
import org.openapitools.codegen.meta.features.*;
import org.openapitools.codegen.model.ModelMap;
import org.openapitools.codegen.model.ModelsMap;
import org.openapitools.codegen.model.OperationMap;
import org.openapitools.codegen.model.OperationsMap;
import org.openapitools.codegen.templating.mustache.CamelCaseLambda;
@@ -69,9 +68,6 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen implements BeanVa
private boolean returnResponse = false;
@Setter
private boolean omitGradleWrapper = false;
@Getter
@Setter
private boolean fixJacksonJsonTypeInfoInheritance = true;
// This is here to potentially warn the user when an option is not supported by the target framework.
private Map<String, List<String>> optionsSupportedPerFramework = new ImmutableMap.Builder<String, List<String>>()
@@ -110,9 +106,6 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen implements BeanVa
public KotlinServerCodegen() {
super();
// Enable proper oneOf/anyOf discriminator handling for polymorphism
legacyDiscriminatorBehavior = false;
modifyFeatureSet(features -> features
.includeDocumentationFeatures(DocumentationFeature.Readme)
.wireFormatFeatures(EnumSet.of(WireFormatFeature.JSON, WireFormatFeature.XML))
@@ -127,9 +120,7 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen implements BeanVa
GlobalFeature.LinkObjects,
GlobalFeature.ParameterStyling
)
.includeSchemaSupportFeatures(
SchemaSupportFeature.allOf,
SchemaSupportFeature.oneOf,
.excludeSchemaSupportFeatures(
SchemaSupportFeature.Polymorphism
)
.excludeParameterFeatures(
@@ -175,7 +166,6 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen implements BeanVa
addSwitch(Constants.RETURN_RESPONSE, Constants.RETURN_RESPONSE_DESC, returnResponse);
addSwitch(Constants.OMIT_GRADLE_WRAPPER, Constants.OMIT_GRADLE_WRAPPER_DESC, omitGradleWrapper);
addSwitch(USE_JAKARTA_EE, Constants.USE_JAKARTA_EE_DESC, useJakartaEe);
addSwitch(Constants.FIX_JACKSON_JSON_TYPE_INFO_INHERITANCE, Constants.FIX_JACKSON_JSON_TYPE_INFO_INHERITANCE_DESC, fixJacksonJsonTypeInfoInheritance);
}
@Override
@@ -245,11 +235,6 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen implements BeanVa
setOmitGradleWrapper(Boolean.parseBoolean(additionalProperties.get(Constants.OMIT_GRADLE_WRAPPER).toString()));
}
if (additionalProperties.containsKey(Constants.FIX_JACKSON_JSON_TYPE_INFO_INHERITANCE)) {
setFixJacksonJsonTypeInfoInheritance(Boolean.parseBoolean(additionalProperties.get(Constants.FIX_JACKSON_JSON_TYPE_INFO_INHERITANCE).toString()));
}
additionalProperties.put(Constants.FIX_JACKSON_JSON_TYPE_INFO_INHERITANCE, fixJacksonJsonTypeInfoInheritance);
writePropertyBack(USE_BEANVALIDATION, useBeanValidation);
// set default library to "ktor"
@@ -396,291 +381,6 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen implements BeanVa
public static final String OMIT_GRADLE_WRAPPER = "omitGradleWrapper";
public static final String OMIT_GRADLE_WRAPPER_DESC = "Whether to omit Gradle wrapper for creating a sub project.";
public static final String IS_KTOR = "isKtor";
public static final String FIX_JACKSON_JSON_TYPE_INFO_INHERITANCE = "fixJacksonJsonTypeInfoInheritance";
public static final String FIX_JACKSON_JSON_TYPE_INFO_INHERITANCE_DESC = "When true (default), ensures Jackson polymorphism works correctly by: (1) always setting visible=true on @JsonTypeInfo, and (2) adding the discriminator property to child models with appropriate default values. When false, visible is only set to true if all children already define the discriminator property.";
}
@Override
public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) {
objs = super.postProcessAllModels(objs);
// For libraries that use Jackson, set up parent-child relationships for discriminator children
// This enables proper polymorphism support with @JsonTypeInfo and @JsonSubTypes annotations
if (usesJacksonSerialization()) {
// Build a map of model name -> model for easy lookup
Map<String, CodegenModel> allModelsMap = new HashMap<>();
for (ModelsMap modelsMap : objs.values()) {
for (ModelMap modelMap : modelsMap.getModels()) {
CodegenModel model = modelMap.getModel();
allModelsMap.put(model.getClassname(), model);
}
}
// First pass: collect all discriminator parent -> children mappings
// Also identify the "true" discriminator owners (not inherited via allOf)
Map<String, String> childToParentMap = new HashMap<>();
Set<String> trueDiscriminatorOwners = new HashSet<>();
for (ModelsMap modelsMap : objs.values()) {
for (ModelMap modelMap : modelsMap.getModels()) {
CodegenModel model = modelMap.getModel();
if (model.getDiscriminator() != null && model.getDiscriminator().getMappedModels() != null
&& !model.getDiscriminator().getMappedModels().isEmpty()) {
String discriminatorPropBaseName = model.getDiscriminator().getPropertyBaseName();
for (CodegenDiscriminator.MappedModel mappedModel : model.getDiscriminator().getMappedModels()) {
childToParentMap.put(mappedModel.getModelName(), model.getClassname());
// If the mapping name equals the model name, check if we can derive
// a better mapping name from the child's discriminator property enum value
if (mappedModel.getMappingName().equals(mappedModel.getModelName())) {
CodegenModel childModel = allModelsMap.get(mappedModel.getModelName());
if (childModel != null) {
// Find the discriminator property in the child model
for (CodegenProperty prop : childModel.getAllVars()) {
if (prop.getBaseName().equals(discriminatorPropBaseName) && prop.isEnum) {
// If it's an enum with exactly one value, use that as the mapping name
Map<String, Object> allowableValues = prop.getAllowableValues();
if (allowableValues != null && allowableValues.containsKey("values")) {
@SuppressWarnings("unchecked")
List<Object> values = (List<Object>) allowableValues.get("values");
if (values != null && values.size() == 1) {
mappedModel.setMappingName(String.valueOf(values.get(0)));
}
}
}
}
}
}
}
// This model owns its discriminator (has mapped models)
trueDiscriminatorOwners.add(model.getClassname());
}
}
}
// Second pass: process child models
for (ModelsMap modelsMap : objs.values()) {
for (ModelMap modelMap : modelsMap.getModels()) {
CodegenModel model = modelMap.getModel();
String parentName = childToParentMap.get(model.getClassname());
if (parentName != null) {
// This model is a child of a discriminator parent
CodegenModel parentModel = allModelsMap.get(parentName);
// Set parent if not already set
if (model.getParent() == null) {
model.setParent(parentName);
}
// If this child has a discriminator but it's inherited (not a true owner),
// remove it - only the parent should have the discriminator annotations
if (model.getDiscriminator() != null && !trueDiscriminatorOwners.contains(model.getClassname())) {
model.setDiscriminator(null);
}
// For allOf pattern: if parent has properties, mark child's inherited properties
// Skip this for oneOf/anyOf patterns where parent properties are merged from children
boolean parentIsOneOfOrAnyOf = parentModel != null
&& ((parentModel.oneOf != null && !parentModel.oneOf.isEmpty())
|| (parentModel.anyOf != null && !parentModel.anyOf.isEmpty()));
if (parentModel != null && parentModel.getHasVars() && !parentIsOneOfOrAnyOf) {
Set<String> parentPropNames = new HashSet<>();
List<String> inheritedPropNamesList = new ArrayList<>();
for (CodegenProperty parentProp : parentModel.getAllVars()) {
parentPropNames.add(parentProp.getBaseName());
inheritedPropNamesList.add(parentProp.getName());
}
// Mark properties inherited from parent
for (CodegenProperty prop : model.getAllVars()) {
if (parentPropNames.contains(prop.getBaseName())) {
prop.isInherited = true;
}
}
for (CodegenProperty prop : model.getVars()) {
if (parentPropNames.contains(prop.getBaseName())) {
prop.isInherited = true;
}
}
for (CodegenProperty prop : model.getRequiredVars()) {
if (parentPropNames.contains(prop.getBaseName())) {
prop.isInherited = true;
}
}
for (CodegenProperty prop : model.getOptionalVars()) {
if (parentPropNames.contains(prop.getBaseName())) {
prop.isInherited = true;
}
}
// Set vendor extension for parent constructor call with inherited properties
if (!inheritedPropNamesList.isEmpty()) {
String parentCtorArgs = String.join(", ", inheritedPropNamesList.stream()
.map(name -> name + " = " + name)
.toArray(String[]::new));
model.getVendorExtensions().put("x-parent-ctor-args", parentCtorArgs);
}
}
}
}
}
// Third pass: set vendor extension for discriminator style and handle fixJacksonJsonTypeInfoInheritance
for (String ownerName : trueDiscriminatorOwners) {
CodegenModel owner = allModelsMap.get(ownerName);
if (owner != null && owner.getDiscriminator() != null) {
String discriminatorPropBaseName = owner.getDiscriminator().getPropertyBaseName();
boolean isOneOfOrAnyOfPattern = (owner.oneOf != null && !owner.oneOf.isEmpty())
|| (owner.anyOf != null && !owner.anyOf.isEmpty());
// hasParentProperties controls whether the sealed class has properties in its constructor
// This should be false for oneOf/anyOf patterns (parent is a type union, no direct properties)
// and true for allOf patterns (parent has properties that children inherit)
boolean hasParentProperties = !isOneOfOrAnyOfPattern;
// visibleTrue controls whether visible=true is set on @JsonTypeInfo
// When fixJacksonJsonTypeInfoInheritance is true, we always set visible=true
// When false, we only set visible=true if the parent has properties (allOf pattern)
boolean visibleTrue;
if (fixJacksonJsonTypeInfoInheritance) {
// When fixJacksonJsonTypeInfoInheritance is true:
// 1. Always set visible=true so Jackson can read the discriminator
// 2. For oneOf/anyOf patterns: add discriminator property to parent and children
visibleTrue = true;
// For oneOf/anyOf patterns, add the discriminator property to the parent sealed class
// This allows accessing the discriminator value from the parent type directly
if (isOneOfOrAnyOfPattern) {
String discriminatorVarName = toVarName(discriminatorPropBaseName);
// Clear all merged properties from the oneOf parent - they belong to children only
// We'll add back just the discriminator property
owner.getVars().clear();
owner.getRequiredVars().clear();
owner.getOptionalVars().clear();
owner.getAllVars().clear();
// Add discriminator property to parent
CodegenProperty parentDiscriminatorProp = new CodegenProperty();
parentDiscriminatorProp.baseName = discriminatorPropBaseName;
parentDiscriminatorProp.name = discriminatorVarName;
parentDiscriminatorProp.dataType = "kotlin.String";
parentDiscriminatorProp.datatypeWithEnum = "kotlin.String";
parentDiscriminatorProp.required = true;
parentDiscriminatorProp.isNullable = false;
parentDiscriminatorProp.isReadOnly = false;
owner.getVars().add(parentDiscriminatorProp);
owner.getRequiredVars().add(parentDiscriminatorProp);
owner.getAllVars().add(parentDiscriminatorProp);
// Parent now has properties (just the discriminator)
hasParentProperties = true;
// Process children: mark discriminator as inherited and set default values
for (CodegenDiscriminator.MappedModel mappedModel : owner.getDiscriminator().getMappedModels()) {
CodegenModel childModel = allModelsMap.get(mappedModel.getModelName());
if (childModel != null) {
boolean hasDiscriminatorProp = false;
String discriminatorDefault = "\"" + mappedModel.getMappingName() + "\"";
// Update existing discriminator property in all lists - mark as inherited
for (CodegenProperty prop : childModel.getVars()) {
if (prop.getBaseName().equals(discriminatorPropBaseName)) {
hasDiscriminatorProp = true;
prop.defaultValue = discriminatorDefault;
prop.dataType = "kotlin.String";
prop.datatypeWithEnum = "kotlin.String";
prop.required = true;
prop.isNullable = false;
prop.isInherited = true;
}
}
for (CodegenProperty prop : childModel.getAllVars()) {
if (prop.getBaseName().equals(discriminatorPropBaseName)) {
prop.defaultValue = discriminatorDefault;
prop.dataType = "kotlin.String";
prop.datatypeWithEnum = "kotlin.String";
prop.required = true;
prop.isNullable = false;
prop.isInherited = true;
}
}
// Move discriminator from optionalVars to requiredVars if needed
CodegenProperty propToMove = null;
for (CodegenProperty prop : childModel.getOptionalVars()) {
if (prop.getBaseName().equals(discriminatorPropBaseName)) {
prop.defaultValue = discriminatorDefault;
prop.dataType = "kotlin.String";
prop.datatypeWithEnum = "kotlin.String";
prop.required = true;
prop.isNullable = false;
prop.isInherited = true;
propToMove = prop;
break;
}
}
if (propToMove != null) {
childModel.getOptionalVars().remove(propToMove);
childModel.getRequiredVars().add(propToMove);
}
// Also update if it's already in requiredVars
for (CodegenProperty prop : childModel.getRequiredVars()) {
if (prop.getBaseName().equals(discriminatorPropBaseName)) {
prop.defaultValue = discriminatorDefault;
prop.dataType = "kotlin.String";
prop.datatypeWithEnum = "kotlin.String";
prop.isNullable = false;
prop.isInherited = true;
}
}
// If child doesn't have the discriminator property, add it as required and inherited
if (!hasDiscriminatorProp) {
CodegenProperty discriminatorProp = new CodegenProperty();
discriminatorProp.baseName = discriminatorPropBaseName;
discriminatorProp.name = discriminatorVarName;
discriminatorProp.dataType = "kotlin.String";
discriminatorProp.datatypeWithEnum = "kotlin.String";
discriminatorProp.defaultValue = discriminatorDefault;
discriminatorProp.required = true;
discriminatorProp.isNullable = false;
discriminatorProp.isReadOnly = false;
discriminatorProp.isInherited = true;
childModel.getVars().add(discriminatorProp);
childModel.getRequiredVars().add(discriminatorProp);
childModel.getAllVars().add(discriminatorProp);
}
// Set parent constructor args for the discriminator property
childModel.getVendorExtensions().put("x-parent-ctor-args",
discriminatorVarName + " = " + discriminatorVarName);
}
}
}
} else {
// When fixJacksonJsonTypeInfoInheritance is false:
// visible=true only for allOf pattern (parent has properties)
visibleTrue = hasParentProperties;
}
// Set on both model and discriminator so it's accessible in different template contexts
owner.getVendorExtensions().put("x-discriminator-has-parent-properties", hasParentProperties);
owner.getDiscriminator().getVendorExtensions().put("x-discriminator-has-parent-properties", hasParentProperties);
owner.getVendorExtensions().put("x-discriminator-visible-true", visibleTrue);
owner.getDiscriminator().getVendorExtensions().put("x-discriminator-visible-true", visibleTrue);
}
}
}
return objs;
}
@Override
@@ -762,16 +462,6 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen implements BeanVa
return Constants.JAVALIN5.equals(library) || Constants.JAVALIN6.equals(library);
}
/**
* Returns true if the current library uses Jackson for JSON serialization.
* This is used to determine if Jackson-specific features like polymorphism annotations should be enabled.
*/
private boolean usesJacksonSerialization() {
return Constants.JAVALIN5.equals(library) ||
Constants.JAVALIN6.equals(library) ||
Constants.JAXRS_SPEC.equals(library);
}
private boolean isKtor2Or3() {
return Constants.KTOR.equals(library) || Constants.KTOR2.equals(library);
}

View File

@@ -247,10 +247,6 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
addSwitch(USE_RESPONSE_ENTITY,
"Whether (when false) to return actual type (e.g. List<Fruit>) and handle non-happy path responses via exceptions flow or (when true) return entire ResponseEntity (e.g. ResponseEntity<List<Fruit>>). If disabled, method are annotated using a @ResponseStatus annotation, which has the status of the first response declared in the Api definition",
useResponseEntity);
addOption(X_KOTLIN_IMPLEMENTS_SKIP, "A list of fully qualified interfaces that should NOT be implemented despite their presence in vendor extension `x-kotlin-implements`. Example: yaml `xKotlinImplementsSkip: [com.some.pack.WithPhotoUrls]` skips implementing the interface in any schema", "empty list");
addOption(X_KOTLIN_IMPLEMENTS_FIELDS_SKIP, "A list of fields per schema name that should NOT be created with `override` keyword despite their presence in vendor extension `x-kotlin-implements-fields` for the schema. Example: yaml `xKotlinImplementsFieldsSkip: Pet: [photoUrls]` skips `override` for `photoUrls` in schema `Pet`", "empty map");
addOption(SCHEMA_IMPLEMENTS, "A map of single interface or a list of interfaces per schema name that should be implemented (serves similar purpose as `x-kotlin-implements`, but is fully decoupled from the api spec). Example: yaml `schemaImplements: {Pet: com.some.pack.WithId, Category: [com.some.pack.CategoryInterface], Dog: [com.some.pack.Canine, com.some.pack.OtherInterface]}` implements interfaces in schemas `Pet` (interface `com.some.pack.WithId`), `Category` (interface `com.some.pack.CategoryInterface`), `Dog`(interfaces `com.some.pack.Canine`, `com.some.pack.OtherInterface`)", "empty map");
addOption(SCHEMA_IMPLEMENTS_FIELDS, "A map of single field or a list of fields per schema name that should be prepended with `override` (serves similar purpose as `x-kotlin-implements-fields`, but is fully decoupled from the api spec). Example: yaml `schemaImplementsFields: {Pet: id, Category: [name, id], Dog: [bark, breed]}` marks fields to be prepended with `override` in schemas `Pet` (field `id`), `Category` (fields `name`, `id`) and `Dog` (fields `bark`, `breed`)", "empty map");
supportedLibraries.put(SPRING_BOOT, "Spring-boot Server application.");
supportedLibraries.put(SPRING_CLOUD_LIBRARY,
"Spring-Cloud-Feign client with Spring-Boot auto-configured settings.");

View File

@@ -249,9 +249,6 @@ public class SpringCodegen extends AbstractJavaCodegen
cliOptions
.add(CliOption.newBoolean(RETURN_SUCCESS_CODE, "Generated server returns 2xx code", returnSuccessCode));
cliOptions.add(CliOption.newBoolean(SPRING_CONTROLLER, "Annotate the generated API as a Spring Controller", useSpringController));
cliOptions.add(CliOption.newString(X_IMPLEMENTS_SKIP, "Ability to choose interfaces that should NOT be implemented in the models despite their presence in vendor extension `x-implements`. Takes a list of fully qualified interface names. Example: yaml `xImplementsSkip: [com.some.pack.WithPhotoUrls]` skips implementing the interface `com.some.pack.WithPhotoUrls` in any schema", "empty list"));
cliOptions.add(CliOption.newString(SCHEMA_IMPLEMENTS, "Ability to supply interfaces per schema that should be implemented (serves similar purpose as vendor extension `x-implements`, but is fully decoupled from the api spec). Example: yaml `schemaImplements: {Pet: com.some.pack.WithId, Category: [com.some.pack.CategoryInterface], Dog: [com.some.pack.Canine, com.some.pack.OtherInterface]}` implements interfaces in schemas `Pet` (interface `com.some.pack.WithId`), `Category` (interface `com.some.pack.CategoryInterface`), `Dog`(interfaces `com.some.pack.Canine`, `com.some.pack.OtherInterface`)", "empty map"));
CliOption requestMappingOpt = new CliOption(REQUEST_MAPPING_OPTION,
"Where to generate the class level @RequestMapping annotation.")
@@ -971,6 +968,11 @@ public class SpringCodegen extends AbstractJavaCodegen
if (model.getVendorExtensions().containsKey("x-jackson-optional-nullable-helpers")) {
model.imports.add("Arrays");
}
// to prevent inheritors (JavaCamelServerCodegen etc.) mistakenly use it
if (getName().contains("spring")) {
model.imports.add("Nullable");
}
}
@Override
@@ -987,11 +989,6 @@ public class SpringCodegen extends AbstractJavaCodegen
codegenModel.imports.remove("Schema");
}
// Only add Nullable import for non-enum models that may have nullable fields
if (!Boolean.TRUE.equals(codegenModel.isEnum)) {
addSpringNullableImport(codegenModel.imports);
}
return codegenModel;
}
@@ -1055,7 +1052,11 @@ public class SpringCodegen extends AbstractJavaCodegen
codegenOperation.imports.addAll(provideArgsClassSet);
}
addSpringNullableImportForOperation(codegenOperation);
// to prevent inheritors (JavaCamelServerCodegen etc.) mistakenly use it
if (getName().contains("spring")) {
codegenOperation.allParams.stream().filter(CodegenParameter::notRequiredOrIsNullable).findAny()
.ifPresent(p -> codegenOperation.imports.add("Nullable"));
}
if (reactive) {
if (DocumentationProvider.SPRINGFOX.equals(getDocumentationProvider())) {
@@ -1218,26 +1219,4 @@ public class SpringCodegen extends AbstractJavaCodegen
extensions.add(VendorExtension.X_SPRING_API_VERSION);
return extensions;
}
private boolean isSpringCodegen() {
return getName().contains("spring");
}
private void addSpringNullableImport(Set<String> imports) {
if (isSpringCodegen()) {
imports.add("Nullable");
}
}
/**
* Adds Spring Nullable import if any parameter is nullable or optional.
*/
private void addSpringNullableImportForOperation(CodegenOperation codegenOperation) {
if (isSpringCodegen()) {
codegenOperation.allParams.stream()
.filter(CodegenParameter::notRequiredOrIsNullable)
.findAny()
.ifPresent(param -> codegenOperation.imports.add("Nullable"));
}
}
}

View File

@@ -78,9 +78,6 @@ public class TypeScriptClientCodegen extends AbstractTypeScriptClientCodegen imp
private static final String USE_OBJECT_PARAMS_SWITCH = "useObjectParameters";
private static final String USE_OBJECT_PARAMS_DESC = "Use aggregate parameter objects as function arguments for api operations instead of passing each parameter as a separate function argument.";
protected static final String TYPESCRIPT_MAJOR_VERSION_SWTICH = "typescriptMajorVersion";
private static final String TYPESCRIPT_MAJOR_VERSION_DESC = "Specify the major version of TypeScript to use in the client code. Default is 5.";
public static final String USE_ERASABLE_SYNTAX = "useErasableSyntax";
public static final String USE_ERASABLE_SYNTAX_DESC = "Use erasable syntax for the generated code. This is a temporary feature and will be removed in the future.";
@@ -100,9 +97,6 @@ public class TypeScriptClientCodegen extends AbstractTypeScriptClientCodegen imp
protected String snapshot = null;
protected ENUM_PROPERTY_NAMING_TYPE enumPropertyNaming = ENUM_PROPERTY_NAMING_TYPE.PascalCase;
@Getter @Setter
protected String typescriptMajorVersion = "5";
private final DateTimeFormatter iso8601Date = DateTimeFormatter.ISO_DATE;
private final DateTimeFormatter iso8601DateTime = DateTimeFormatter.ISO_DATE_TIME;
@@ -137,7 +131,6 @@ public class TypeScriptClientCodegen extends AbstractTypeScriptClientCodegen imp
cliOptions.add(new CliOption(TypeScriptClientCodegen.USE_RXJS_SWITCH, TypeScriptClientCodegen.USE_RXJS_SWITCH_DESC).defaultValue("false"));
cliOptions.add(new CliOption(TypeScriptClientCodegen.USE_OBJECT_PARAMS_SWITCH, TypeScriptClientCodegen.USE_OBJECT_PARAMS_DESC).defaultValue("false"));
cliOptions.add(new CliOption(TypeScriptClientCodegen.USE_INVERSIFY_SWITCH, TypeScriptClientCodegen.USE_INVERSIFY_SWITCH_DESC).defaultValue("false"));
cliOptions.add(new CliOption(TypeScriptClientCodegen.TYPESCRIPT_MAJOR_VERSION_SWTICH, TypeScriptClientCodegen.TYPESCRIPT_MAJOR_VERSION_DESC).defaultValue(this.getTypescriptMajorVersion()));
cliOptions.add(new CliOption(TypeScriptClientCodegen.IMPORT_FILE_EXTENSION_SWITCH, TypeScriptClientCodegen.IMPORT_FILE_EXTENSION_SWITCH_DESC));
cliOptions.add(new CliOption(TypeScriptClientCodegen.USE_ERASABLE_SYNTAX, TypeScriptClientCodegen.USE_ERASABLE_SYNTAX_DESC).defaultValue("false"));
@@ -502,8 +495,6 @@ public class TypeScriptClientCodegen extends AbstractTypeScriptClientCodegen imp
if (additionalProperties.containsKey(NPM_REPOSITORY)) {
setNpmRepository(additionalProperties.get(NPM_REPOSITORY).toString());
}
additionalProperties.put(TYPESCRIPT_MAJOR_VERSION_SWTICH, typescriptMajorVersion);
}
private String getHttpLibForFramework(String object) {

View File

@@ -117,7 +117,7 @@ ext {
jackson_version = "2.19.2"
jackson_databind_version = "2.19.2"
{{#openApiNullable}}
jackson_databind_nullable_version = "0.2.9"
jackson_databind_nullable_version = "0.2.8"
{{/openApiNullable}}
jakarta_annotation_version = "1.3.5"
{{#useBeanValidation}}

View File

@@ -117,7 +117,7 @@ ext {
jackson_version = "2.19.2"
jackson_databind_version = "2.19.2"
{{#openApiNullable}}
jackson_databind_nullable_version = "0.2.9"
jackson_databind_nullable_version = "0.2.8"
{{/openApiNullable}}
jakarta_annotation_version = "1.3.5"
httpclient_version = "5.1.3"

View File

@@ -354,7 +354,7 @@
<jackson-version>2.19.2</jackson-version>
<jackson-databind-version>2.19.2</jackson-databind-version>
{{#openApiNullable}}
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
<jackson-databind-nullable-version>0.2.8</jackson-databind-nullable-version>
{{/openApiNullable}}
{{#useJakartaEe}}
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>

View File

@@ -34,12 +34,6 @@ import feign.jackson.JacksonEncoder;
import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder;
{{/gson}}
{{#feign-okhttp}}
import feign.okhttp.OkHttpClient;
{{/feign-okhttp}}
{{#feign-hc5}}
import feign.hc5.ApacheHttp5Client;
{{/feign-hc5}}
import feign.slf4j.Slf4jLogger;
import {{invokerPackage}}.auth.HttpBasicAuth;
import {{invokerPackage}}.auth.HttpBearerAuth;
@@ -71,24 +65,12 @@ public class ApiClient {
protected String basePath = "{{{basePath}}}";
protected Map<String, RequestInterceptor> apiAuthorizations;
protected Feign.Builder feignBuilder;
{{#feign-okhttp}}
private static final OkHttpClient OK_HTTP_CLIENT = new OkHttpClient();
{{/feign-okhttp}}
{{#feign-hc5}}
private static final ApacheHttp5Client APACHE_HTTP5_CLIENT = new ApacheHttp5Client();
{{/feign-hc5}}
public ApiClient() {
apiAuthorizations = new LinkedHashMap<String, RequestInterceptor>();
{{#jackson}}
objectMapper = createObjectMapper();
feignBuilder = Feign.builder()
{{#feign-okhttp}}
.client(OK_HTTP_CLIENT)
{{/feign-okhttp}}
{{#feign-hc5}}
.client(APACHE_HTTP5_CLIENT)
{{/feign-hc5}}
.encoder(new FormEncoder(new JacksonEncoder(objectMapper)))
.decoder(new ApiResponseDecoder(objectMapper))
{{#hasOAuthMethods}}
@@ -99,12 +81,6 @@ public class ApiClient {
{{/jackson}}
{{#gson}}
feignBuilder = Feign.builder()
{{#feign-okhttp}}
.client(OK_HTTP_CLIENT)
{{/feign-okhttp}}
{{#feign-hc5}}
.client(APACHE_HTTP5_CLIENT)
{{/feign-hc5}}
.encoder(new FormEncoder(new GsonEncoder()))
.decoder(new GsonDecoder())
{{#hasOAuthMethods}}

View File

@@ -107,7 +107,7 @@ ext {
jackson_databind_version = "2.19.2"
{{/jackson}}
{{#openApiNullable}}
jackson_databind_nullable_version = "0.2.9"
jackson_databind_nullable_version = "0.2.8"
{{/openApiNullable}}
jakarta_annotation_version = "1.3.5"
feign_version = "13.5"

View File

@@ -416,7 +416,7 @@
<gson-version>2.10.1</gson-version>
{{/gson}}
{{#openApiNullable}}
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
<jackson-databind-nullable-version>0.2.8</jackson-databind-nullable-version>
{{/openApiNullable}}
{{#useJakartaEe}}
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>

View File

@@ -101,7 +101,7 @@ ext {
jackson_version = "2.19.2"
jackson_databind_version = "2.19.2"
{{#openApiNullable}}
jackson_databind_nullable_version = "0.2.9"
jackson_databind_nullable_version = "0.2.8"
{{/openApiNullable}}
jakarta_annotation_version = "1.3.5"
google_api_client_version = "1.32.2"

View File

@@ -313,7 +313,7 @@
<jackson-version>2.19.2</jackson-version>
<jackson-databind-version>2.19.2</jackson-databind-version>
{{#openApiNullable}}
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
<jackson-databind-nullable-version>0.2.8</jackson-databind-nullable-version>
{{/openApiNullable}}
{{#joda}}
<jodatime-version>2.9.9</jodatime-version>

View File

@@ -107,7 +107,7 @@ ext {
jackson_version = "2.19.2"
jackson_databind_version = "2.19.2"
{{#openApiNullable}}
jackson_databind_nullable_version = "0.2.9"
jackson_databind_nullable_version = "0.2.8"
{{/openApiNullable}}
jakarta_annotation_version = "1.3.5"
{{#useBeanValidation}}

View File

@@ -24,7 +24,7 @@ lazy val root = (project in file(".")).
{{/joda}}
"com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.19.2" % "compile",
{{#openApiNullable}}
"org.openapitools" % "jackson-databind-nullable" % "0.2.9" % "compile",
"org.openapitools" % "jackson-databind-nullable" % "0.2.8" % "compile",
{{/openApiNullable}}
{{#hasOAuthMethods}}
"com.github.scribejava" % "scribejava-apis" % "8.3.1" % "compile",

View File

@@ -407,7 +407,7 @@
<jersey-version>2.37</jersey-version>
<jackson-version>2.19.2</jackson-version>
<jackson-databind-version>2.19.2</jackson-databind-version>
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
<jackson-databind-nullable-version>0.2.8</jackson-databind-nullable-version>
{{#useJakartaEe}}
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>
<beanvalidation-version>3.0.2</beanvalidation-version>

View File

@@ -102,7 +102,7 @@ ext {
jackson_version = "2.19.2"
jackson_databind_version = "2.19.2"
{{#openApiNullable}}
jackson_databind_nullable_version = "0.2.9"
jackson_databind_nullable_version = "0.2.8"
{{/openApiNullable}}
jakarta_annotation_version = "2.1.0"
{{#useBeanValidation}}

View File

@@ -24,7 +24,7 @@ lazy val root = (project in file(".")).
{{/joda}}
"com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.19.2" % "compile",
{{#openApiNullable}}
"org.openapitools" % "jackson-databind-nullable" % "0.2.9" % "compile",
"org.openapitools" % "jackson-databind-nullable" % "0.2.8" % "compile",
{{/openApiNullable}}
{{#hasOAuthMethods}}
"com.github.scribejava" % "scribejava-apis" % "8.3.1" % "compile",

View File

@@ -407,7 +407,7 @@
<jersey-version>3.1.11</jersey-version>
<jackson-version>2.19.2</jackson-version>
<jackson-databind-version>2.19.2</jackson-databind-version>
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
<jackson-databind-nullable-version>0.2.8</jackson-databind-nullable-version>
{{#useJakartaEe}}
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>
<beanvalidation-version>3.0.2</beanvalidation-version>

View File

@@ -102,7 +102,7 @@ dependencies {
implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version"
implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_version"
implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version"
implementation "org.openapitools:jackson-databind-nullable:0.2.9"
implementation "org.openapitools:jackson-databind-nullable:0.2.8"
implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version"
{{#useBeanValidation}}
implementation "jakarta.validation:jakarta.validation-api:$beanvalidation_version"

View File

@@ -300,7 +300,7 @@
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<jackson-version>2.19.2</jackson-version>
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
<jackson-databind-nullable-version>0.2.8</jackson-databind-nullable-version>
{{#useJakartaEe}}
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>
<beanvalidation-version>3.0.2</beanvalidation-version>

View File

@@ -132,7 +132,7 @@ dependencies {
implementation 'io.gsonfire:gson-fire:1.9.0'
implementation 'jakarta.ws.rs:jakarta.ws.rs-api:2.1.6'
{{#openApiNullable}}
implementation 'org.openapitools:jackson-databind-nullable:0.2.9'
implementation 'org.openapitools:jackson-databind-nullable:0.2.8'
{{/openApiNullable}}
{{#withAWSV4Signature}}
implementation 'software.amazon.awssdk:auth:2.20.157'

View File

@@ -16,7 +16,7 @@ lazy val root = (project in file(".")).
"org.apache.commons" % "commons-lang3" % "3.18.0",
"jakarta.ws.rs" % "jakarta.ws.rs-api" % "2.1.6",
{{#openApiNullable}}
"org.openapitools" % "jackson-databind-nullable" % "0.2.9",
"org.openapitools" % "jackson-databind-nullable" % "0.2.8",
{{/openApiNullable}}
{{#withAWSV4Signature}}
"software.amazon.awssdk" % "auth" % "2.20.157",

View File

@@ -385,16 +385,16 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
{{#isArray}}
{{#items.isModel}}
{{#required}}
if (jsonObj.get("{{{baseName}}}") != null{{#isNullable}} && !jsonObj.get("{{{baseName}}}").isJsonNull(){{/isNullable}}) {
if (!jsonObj.get("{{{baseName}}}").isJsonArray()) {
throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString()));
}
JsonArray jsonArray{{name}} = jsonObj.getAsJsonArray("{{{baseName}}}");
// validate the required field `{{{baseName}}}` (array)
for (int i = 0; i < jsonArray{{name}}.size(); i++) {
{{{items.dataType}}}.validateJsonElement(jsonArray{{name}}.get(i));
}
// ensure the json data is an array
if (!jsonObj.get("{{{baseName}}}").isJsonArray()) {
throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString()));
}
JsonArray jsonArray{{name}} = jsonObj.getAsJsonArray("{{{baseName}}}");
// validate the required field `{{{baseName}}}` (array)
for (int i = 0; i < jsonArray{{name}}.size(); i++) {
{{{items.dataType}}}.validateJsonElement(jsonArray{{name}}.get(i));
};
{{/required}}
{{^required}}
if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) {
@@ -424,7 +424,7 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
// ensure the required json array is present
if (jsonObj.get("{{{baseName}}}") == null) {
throw new IllegalArgumentException("Expected the field `linkedContent` to be an array in the JSON string but got `null`");
} else if (!jsonObj.get("{{{baseName}}}").isJsonArray(){{#isNullable}} && !jsonObj.get("{{baseName}}").isJsonNull(){{/isNullable}}) {
} else if (!jsonObj.get("{{{baseName}}}").isJsonArray()) {
throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString()));
}
{{/required}}
@@ -438,14 +438,8 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
{{/isString}}
{{#isModel}}
{{#required}}
{{#isNullable}}
if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) {
{{/isNullable}}
// validate the required field `{{{baseName}}}`
{{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}"));
{{#isNullable}}
}
{{/isNullable}}
{{/required}}
{{^required}}
// validate the optional field `{{{baseName}}}`
@@ -456,14 +450,8 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
{{/isModel}}
{{#isEnum}}
{{#required}}
{{#isNullable}}
if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) {
{{/isNullable}}
// validate the required field `{{{baseName}}}`
{{{datatypeWithEnum}}}.validateJsonElement(jsonObj.get("{{{baseName}}}"));
{{#isNullable}}
}
{{/isNullable}}
{{/required}}
{{^required}}
// validate the optional field `{{{baseName}}}`
@@ -474,14 +462,8 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
{{/isEnum}}
{{#isEnumRef}}
{{#required}}
{{#isNullable}}
if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) {
{{/isNullable}}
// validate the required field `{{{baseName}}}`
{{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}"));
{{#isNullable}}
}
{{/isNullable}}
{{/required}}
{{^required}}
// validate the optional field `{{{baseName}}}`

View File

@@ -416,7 +416,7 @@
<gson-version>2.10.1</gson-version>
<commons-lang3-version>3.18.0</commons-lang3-version>
{{#openApiNullable}}
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
<jackson-databind-nullable-version>0.2.8</jackson-databind-nullable-version>
{{/openApiNullable}}
{{#joda}}
<jodatime-version>2.12.0</jodatime-version>

View File

@@ -109,7 +109,7 @@ ext {
jackson_version = "2.19.2"
jackson_databind_version = "2.19.2"
{{#openApiNullable}}
jackson_databind_nullable_version = "0.2.9"
jackson_databind_nullable_version = "0.2.8"
{{/openApiNullable}}
{{/jackson}}
{{#gson}}

View File

@@ -18,7 +18,7 @@ lazy val root = (project in file(".")).
"com.fasterxml.jackson.core" % "jackson-annotations" % "2.19.2",
"com.fasterxml.jackson.core" % "jackson-databind" % "2.19.2",
{{#openApiNullable}}
"org.openapitools" % "jackson-databind-nullable" % "0.2.9",
"org.openapitools" % "jackson-databind-nullable" % "0.2.8",
{{/openApiNullable}}
{{#withXml}}
"com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.13.4.1",

View File

@@ -354,7 +354,7 @@
{{#jackson}}
<jackson-version>2.19.2</jackson-version>
<jackson-databind-version>2.19.2</jackson-databind-version>
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
<jackson-databind-nullable-version>0.2.8</jackson-databind-nullable-version>
{{/jackson}}
{{#useJakartaEe}}
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>

View File

@@ -106,7 +106,7 @@ ext {
jackson_version = "2.19.2"
jackson_databind_version = "2.19.2"
{{#openApiNullable}}
jackson_databind_nullable_version = "0.2.9"
jackson_databind_nullable_version = "0.2.8"
{{/openApiNullable}}
spring_web_version = "6.1.21"
jakarta_annotation_version = "2.1.1"

View File

@@ -350,7 +350,7 @@
<jackson-version>2.19.2</jackson-version>
<jackson-databind-version>2.19.2</jackson-databind-version>
{{#openApiNullable}}
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
<jackson-databind-nullable-version>0.2.8</jackson-databind-nullable-version>
{{/openApiNullable}}
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>
{{#joda}}

View File

@@ -101,7 +101,7 @@ ext {
jackson_version = "2.19.2"
jackson_databind_version = "2.19.2"
{{#openApiNullable}}
jackson_databind_nullable_version = "0.2.9"
jackson_databind_nullable_version = "0.2.8"
{{/openApiNullable}}
jakarta_annotation_version = "1.3.5"
threetenbp_version = "2.9.10"

View File

@@ -301,7 +301,7 @@
<jackson-version>2.19.2</jackson-version>
<jackson-databind-version>2.19.2</jackson-databind-version>
{{#openApiNullable}}
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
<jackson-databind-nullable-version>0.2.8</jackson-databind-nullable-version>
{{/openApiNullable}}
{{#useJakartaEe}}
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>

View File

@@ -118,7 +118,7 @@ ext {
jackson_version = "2.19.2"
jackson_databind_version = "2.19.2"
{{#openApiNullable}}
jackson_databind_nullable_version = "0.2.9"
jackson_databind_nullable_version = "0.2.8"
{{/openApiNullable}}
{{#useJakartaEe}}
spring_web_version = "6.2.8"

View File

@@ -364,7 +364,7 @@
<jackson-version>2.19.2</jackson-version>
<jackson-databind-version>2.19.2</jackson-databind-version>
{{#openApiNullable}}
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
<jackson-databind-nullable-version>0.2.8</jackson-databind-nullable-version>
{{/openApiNullable}}
{{#useJakartaEe}}
<spring-web-version>6.2.8</spring-web-version>

View File

@@ -104,7 +104,7 @@ ext {
jackson_databind_version = "2.19.2"
javax_ws_rs_api_version = "2.1.1"
{{#openApiNullable}}
jackson_databind_nullable_version = "0.2.9"
jackson_databind_nullable_version = "0.2.8"
{{/openApiNullable}}
{{/jackson}}
{{#usePlayWS}}

View File

@@ -386,7 +386,7 @@
<jackson-databind-version>2.19.2</jackson-databind-version>
<jackson-version>2.19.2</jackson-version>
{{#openApiNullable}}
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
<jackson-databind-nullable-version>0.2.8</jackson-databind-nullable-version>
{{/openApiNullable}}
<javax.ws.rs-api-version>2.1.1</javax.ws.rs-api-version>
{{/jackson}}

View File

@@ -35,7 +35,7 @@ ext {
vertx_version = "{{#supportVertxFuture}}4.0.0{{/supportVertxFuture}}{{^supportVertxFuture}}3.5.2{{/supportVertxFuture}}"
junit_version = "5.10.3"
{{#openApiNullable}}
jackson_databind_nullable_version = "0.2.9"
jackson_databind_nullable_version = "0.2.8"
{{/openApiNullable}}
jakarta_annotation_version = "1.3.5"
}

View File

@@ -308,7 +308,7 @@
{{/swagger2AnnotationLibrary}}
<jackson-version>2.19.2</jackson-version>
<jackson-databind>2.19.2</jackson-databind>
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
<jackson-databind-nullable-version>0.2.8</jackson-databind-nullable-version>
{{#useJakartaEe}}
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>
{{/useJakartaEe}}

View File

@@ -147,7 +147,7 @@ ext {
jackson_version = "2.19.2"
jackson_databind_version = "2.19.2"
{{#openApiNullable}}
jackson_databind_nullable_version = "0.2.9"
jackson_databind_nullable_version = "0.2.8"
{{/openApiNullable}}
{{#joda}}
jodatime_version = "2.9.9"

View File

@@ -170,7 +170,7 @@
<jackson-version>2.19.2</jackson-version>
<jackson-databind-version>2.19.2</jackson-databind-version>
{{#openApiNullable}}
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
<jackson-databind-nullable-version>0.2.8</jackson-databind-nullable-version>
{{/openApiNullable}}
{{#useJakartaEe}}
<spring-boot-version>3.2.12</spring-boot-version>

View File

@@ -51,7 +51,7 @@
<smallrye.rest.client.version>1.2.1</smallrye.rest.client.version>
{{/useMutiny}}
{{#openApiNullable}}
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
<jackson-databind-nullable-version>0.2.8</jackson-databind-nullable-version>
{{/openApiNullable}}
</properties>
<dependencyManagement>

View File

@@ -208,7 +208,7 @@
<jakarta.ws.rs-version>2.1.6</jakarta.ws.rs-version>
{{/useJakartaEe}}
{{#openApiNullable}}
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
<jackson-databind-nullable-version>0.2.8</jackson-databind-nullable-version>
{{/openApiNullable}}
{{#useSwaggerV3Annotations}}
<io.swagger.v3.annotations.version>2.2.21</io.swagger.v3.annotations.version>

View File

@@ -208,7 +208,7 @@
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>0.2.9</version>
<version>0.2.8</version>
</dependency>
{{/openApiNullable}}
{{#useBeanValidation}}

View File

@@ -139,7 +139,7 @@
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
{{^parentOverridden}}
<version>0.2.9</version>
<version>0.2.8</version>
{{/parentOverridden}}
</dependency>
{{/openApiNullable}}

View File

@@ -86,7 +86,7 @@
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>0.2.9</version>
<version>0.2.8</version>
</dependency>
{{/openApiNullable}}
{{#lombok}}

View File

@@ -71,7 +71,7 @@ public:
int getHttpResponseCode() const;
Q_SIGNALS:
void on_execution_finished({{#cppNamespaceDeclarations}}{{this}}::{{/cppNamespaceDeclarations}}{{prefix}}HttpRequestWorker *worker);
void on_execution_finished({{prefix}}HttpRequestWorker *worker);
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
private:

View File

@@ -116,22 +116,20 @@ Do not edit the class manually.
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>0.2.9</version>
<version>0.2.8</version>
</dependency>
{{#swagger1AnnotationLibrary}}
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.6.3</version>
</dependency>
{{/swagger1AnnotationLibrary}}
{{#swagger2AnnotationLibrary}}
{{#oas3}}
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>2.2.8</version>
</dependency>
{{/swagger2AnnotationLibrary}}
{{/oas3}}
{{#jackson}}
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>

View File

@@ -18,7 +18,7 @@
<properties>
{{#openApiNullable}}
<version.jackson.databind.nullable>0.2.9</version.jackson.databind.nullable>
<version.jackson.databind.nullable>0.2.8</version.jackson.databind.nullable>
{{/openApiNullable}}
</properties>

View File

@@ -19,7 +19,7 @@
<properties>
{{#openApiNullable}}
<version.jackson.databind.nullable>0.2.9</version.jackson.databind.nullable>
<version.jackson.databind.nullable>0.2.8</version.jackson.databind.nullable>
{{/openApiNullable}}
</properties>

View File

@@ -19,7 +19,7 @@
<properties>
{{#openApiNullable}}
<version.jackson.databind.nullable>0.2.9</version.jackson.databind.nullable>
<version.jackson.databind.nullable>0.2.7</version.jackson.databind.nullable>
{{/openApiNullable}}
</properties>

View File

@@ -20,7 +20,7 @@
<properties>
<mainClass>{{{invokerPackage}}}.Main</mainClass>
{{#openApiNullable}}
<version.jackson.databind.nullable>0.2.9</version.jackson.databind.nullable>
<version.jackson.databind.nullable>0.2.8</version.jackson.databind.nullable>
{{/openApiNullable}}
</properties>

View File

@@ -4,16 +4,8 @@ package {{packageName}}.infrastructure
* Defines a config object for a given part of a multi-part request.
* NOTE: Headers is a Map<String,String> because rfc2616 defines
* multi-valued headers as csv-only.
*
* @property headers The headers for this part
* @property body The body content for this part
* @property serializer Optional custom serializer for JSON content. When provided, this will be
* used instead of the default serialization for parts with application/json
* content-type. This allows capturing type information at the call site to
* avoid issues with type erasure in kotlinx.serialization.
*/
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}data class PartConfig<T>(
val headers: MutableMap<String, String> = mutableMapOf(),
val body: T? = null,
val serializer: ((Any?) -> String)? = null
val body: T? = null
)

View File

@@ -46,9 +46,6 @@ import {{packageName}}.infrastructure.RequestMethod
import {{packageName}}.infrastructure.ResponseType
import {{packageName}}.infrastructure.Success
import {{packageName}}.infrastructure.toMultiValue
{{#kotlinx_serialization}}
import {{packageName}}.infrastructure.Serializer
{{/kotlinx_serialization}}
{{#operations}}
{{#nonPublicApi}}internal {{/nonPublicApi}}{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}open {{/nonPublicApi}}class {{classname}}(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) {
@@ -202,7 +199,7 @@ import {{packageName}}.infrastructure.Serializer
}}{{#bodyParams}}{{{paramName}}}{{/bodyParams}}{{/hasBodyParam}}{{^hasBodyParam}}{{!
}}{{^hasFormParams}}null{{/hasFormParams}}{{!
}}{{#hasFormParams}}mapOf({{#formParams}}
"{{#lambda.escapeDollar}}{{{baseName}}}{{/lambda.escapeDollar}}" to PartConfig(body = {{{paramName}}}{{#isEnum}}{{^required}}?{{/required}}.value{{/isEnum}}, headers = mutableMapOf({{#contentType}}"Content-Type" to "{{contentType}}"{{/contentType}}){{#contentType}}{{^isFile}}, serializer = {{#kotlinx_serialization}}{ obj -> Serializer.kotlinxSerializationJson.encodeToString<{{{dataType}}}>(obj as {{{dataType}}}) }{{/kotlinx_serialization}}{{^kotlinx_serialization}}null{{/kotlinx_serialization}}{{/isFile}}{{/contentType}}),{{!
"{{#lambda.escapeDollar}}{{{baseName}}}{{/lambda.escapeDollar}}" to PartConfig(body = {{{paramName}}}{{#isEnum}}{{^required}}?{{/required}}.value{{/isEnum}}, headers = mutableMapOf({{#contentType}}"Content-Type" to "{{contentType}}"{{/contentType}})),{{!
}}{{/formParams}}){{/hasFormParams}}{{!
}}{{/hasBodyParam}}
val localVariableQuery: MultiValueMap = {{^hasQueryParams}}mutableMapOf()

View File

@@ -115,25 +115,6 @@ import com.squareup.moshi.adapter
return contentType ?: "application/octet-stream"
}
/**
* Builds headers for a multipart form-data part.
* OkHttp requires Content-Type to be passed via the RequestBody parameter, not in headers.
* This function filters out Content-Type and builds the appropriate Content-Disposition header.
*
* @param name The field name
* @param headers The headers from the PartConfig (may include Content-Type)
* @param filename Optional filename for file uploads
* @return Headers object ready for addPart()
*/
protected fun buildPartHeaders(name: String, headers: Map<String, String>, filename: String? = null): Headers {
val disposition = if (filename != null) {
"form-data; name=\"$name\"; filename=\"$filename\""
} else {
"form-data; name=\"$name\""
}
return (headers.filterKeys { it != "Content-Type" } + ("Content-Disposition" to disposition)).toHeaders()
}
/**
* Adds a File to a MultipartBody.Builder
* Defined a helper in the requestBody method to not duplicate code
@@ -146,48 +127,15 @@ import com.squareup.moshi.adapter
* @see requestBody
*/
protected fun MultipartBody.Builder.addPartToMultiPart(name: String, headers: Map<String, String>, file: File) {
val partHeaders = headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${file.name}\"")
val fileMediaType = guessContentTypeFromFile(file).toMediaTypeOrNull()
addPart(
buildPartHeaders(name, headers, file.name),
partHeaders.toHeaders(),
file.asRequestBody(fileMediaType)
)
}
/**
* Serializes a multipart body part based on its content type.
* Uses JSON serialization for application/json content types, otherwise converts to string.
*
* @param obj The object to serialize
* @param contentType The Content-Type header value, if any
* @param serializer Optional custom serializer (used for kotlinx.serialization to preserve type info)
* @return The serialized string representation
*/
protected fun serializePartBody(obj: Any?, contentType: String?, serializer: ((Any?) -> String)?): String {
// Use custom serializer if provided (for kotlinx.serialization with captured type info)
if (serializer != null) {
return serializer(obj)
}
return if (contentType?.contains("json") == true) {
{{#moshi}}
Serializer.moshi.adapter(Any::class.java).toJson(obj)
{{/moshi}}
{{#gson}}
Serializer.gson.toJson(obj)
{{/gson}}
{{#jackson}}
Serializer.jacksonObjectMapper.writeValueAsString(obj)
{{/jackson}}
{{#kotlinx_serialization}}
// Note: Without a custom serializer, kotlinx.serialization cannot serialize Any?
// The custom serializer should be provided at PartConfig creation to capture type info
parameterToString(obj)
{{/kotlinx_serialization}}
} else {
parameterToString(obj)
}
}
/**
* Adds any type to a MultipartBody.Builder
* Defined a helper in the requestBody method to not duplicate code
@@ -196,17 +144,15 @@ import com.squareup.moshi.adapter
* @param name The field name to add in the request
* @param headers The headers that are in the PartConfig
* @param obj The field name to add in the request
* @param serializer Optional custom serializer for this part
* @return The method returns Unit but the new Part is added to the Builder that the extension function is applying on
* @see requestBody
*/
protected fun MultipartBody.Builder.addPartToMultiPart(name: String, headers: Map<String, String>, obj: Any?, serializer: ((Any?) -> String)? = null) {
val partContentType = headers["Content-Type"]
val partMediaType = partContentType?.toMediaTypeOrNull()
val partBody = serializePartBody(obj, partContentType, serializer)
protected fun <T> MultipartBody.Builder.addPartToMultiPart(name: String, headers: Map<String, String>, obj: T?) {
val partHeaders = headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
buildPartHeaders(name, headers),
partBody.toRequestBody(partMediaType)
partHeaders.toHeaders(),
parameterToString(obj).toRequestBody(null)
)
}
@@ -228,11 +174,11 @@ import com.squareup.moshi.adapter
if (it is File) {
addPartToMultiPart(name, part.headers, it)
} else {
addPartToMultiPart(name, part.headers, it, part.serializer)
addPartToMultiPart(name, part.headers, it)
}
}
}
else -> addPartToMultiPart(name, part.headers, part.body, part.serializer)
else -> addPartToMultiPart(name, part.headers, part.body)
}
}
}.build()

View File

@@ -11,10 +11,6 @@ import io.ktor.client.request.forms.formData
import io.ktor.client.engine.HttpClientEngine
import kotlinx.serialization.json.Json
import io.ktor.http.ParametersBuilder
import io.ktor.http.Headers
import io.ktor.http.HttpHeaders
import io.ktor.http.ContentType
import io.ktor.http.content.PartData
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
@@ -80,31 +76,11 @@ import kotlinx.serialization.encoding.*
{{#formParams}}
{{#isArray}}
{{{paramName}}}?.onEach {
{{#isFile}}append(it){{/isFile}}{{^isFile}}append("{{{baseName}}}", it.toString()){{/isFile}}
{{#isFile}}append(it){{/isFile}}{{^isFile}}append("{{{baseName}}}", it){{/isFile}}
}
{{/isArray}}
{{^isArray}}
{{#isFile}}
{{{paramName}}}?.apply { append({{{baseName}}}) }
{{/isFile}}
{{^isFile}}
{{#isPrimitiveType}}
{{#isString}}
{{{paramName}}}?.apply { append("{{{baseName}}}", {{{paramName}}}) }
{{/isString}}
{{^isString}}
{{{paramName}}}?.apply { append("{{{baseName}}}", {{{paramName}}}.toString()) }
{{/isString}}
{{/isPrimitiveType}}
{{^isPrimitiveType}}
{{#isEnumOrRef}}
{{{paramName}}}?.apply { append("{{{baseName}}}", {{{paramName}}}.value.toString()) }
{{/isEnumOrRef}}
{{^isEnumOrRef}}
{{{paramName}}}?.apply { append("{{{baseName}}}", ApiClient.JSON_DEFAULT.encodeToString({{{dataType}}}.serializer(), {{{paramName}}})) }
{{/isEnumOrRef}}
{{/isPrimitiveType}}
{{/isFile}}
{{{paramName}}}?.apply { {{#isFile}}append({{{baseName}}}){{/isFile}}{{^isFile}}append("{{{baseName}}}", {{^isEnumOrRef}}{{{paramName}}}{{/isEnumOrRef}}{{#isEnumOrRef}}{{{paramName}}}.value{{/isEnumOrRef}}){{/isFile}} }
{{/isArray}}
{{/formParams}}
}

View File

@@ -12,38 +12,23 @@ import java.io.Serializable
{{/isKtor}}
/**
* {{{description}}}
{{#isKtor}}
{{#vars}}
* @param {{{name}}} {{{description}}}
{{/vars}}
{{/isKtor}}
{{^isKtor}}
{{^discriminator}}
{{#vars}}
* @param {{{name}}} {{{description}}}
{{/vars}}
{{/discriminator}}
{{#discriminator}}
{{#vendorExtensions.x-discriminator-has-parent-properties}}
{{#vars}}
* @param {{{name}}} {{{description}}}
{{/vars}}
{{/vendorExtensions.x-discriminator-has-parent-properties}}
{{/discriminator}}
{{/isKtor}}
*/
{{#parcelizeModels}}
@Parcelize
{{/parcelizeModels}}
{{#isKtor}}
@Serializable
{{/isKtor}}
{{#hasVars}}data {{/hasVars}}class {{classname}}(
{{#requiredVars}}
{{>data_class_req_var}}{{^-last}},
{{/-last}}{{/requiredVars}}{{#hasRequired}}{{#hasOptional}},
{{/hasOptional}}{{/hasRequired}}{{#optionalVars}}{{>data_class_opt_var}}{{^-last}},
{{/-last}}{{/optionalVars}}
)
){{^isKtor}}{{^serializableModel}}{{#parcelizeModels}} : Parcelable{{/parcelizeModels}}{{/serializableModel}}{{^parcelizeModels}}{{#serializableModel}}: Serializable {{/serializableModel}}{{/parcelizeModels}}{{#parcelizeModels}}{{#serializableModel}} : Parcelable, Serializable {{/serializableModel}}{{/parcelizeModels}}{{/isKtor}}
{{#vendorExtensions.x-has-data-class-body}}
{
{{/vendorExtensions.x-has-data-class-body}}
@@ -67,53 +52,3 @@ import java.io.Serializable
{{#vendorExtensions.x-has-data-class-body}}
}
{{/vendorExtensions.x-has-data-class-body}}
{{/isKtor}}
{{^isKtor}}
{{#discriminator}}
{{>typeInfoAnnotation}}
{{#vendorExtensions.x-discriminator-has-parent-properties}}
sealed class {{classname}}(
{{#requiredVars}}
{{>data_class_sealed_var}}{{^-last}},
{{/-last}}{{/requiredVars}}{{#hasRequired}}{{#hasOptional}},
{{/hasOptional}}{{/hasRequired}}{{#optionalVars}}{{>data_class_sealed_var}}{{^-last}},
{{/-last}}{{/optionalVars}}
)
{{/vendorExtensions.x-discriminator-has-parent-properties}}
{{^vendorExtensions.x-discriminator-has-parent-properties}}
sealed class {{classname}}
{{/vendorExtensions.x-discriminator-has-parent-properties}}
{{/discriminator}}
{{^discriminator}}
{{#hasVars}}data {{/hasVars}}class {{classname}}(
{{#requiredVars}}
{{>data_class_req_var}}{{^-last}},
{{/-last}}{{/requiredVars}}{{#hasRequired}}{{#hasOptional}},
{{/hasOptional}}{{/hasRequired}}{{#optionalVars}}{{>data_class_opt_var}}{{^-last}},
{{/-last}}{{/optionalVars}}
){{#parent}} : {{{.}}}({{#vendorExtensions.x-parent-ctor-args}}{{{.}}}{{/vendorExtensions.x-parent-ctor-args}}){{/parent}}{{^parent}}{{^serializableModel}}{{#parcelizeModels}} : Parcelable{{/parcelizeModels}}{{/serializableModel}}{{^parcelizeModels}}{{#serializableModel}}: Serializable {{/serializableModel}}{{/parcelizeModels}}{{#parcelizeModels}}{{#serializableModel}} : Parcelable, Serializable {{/serializableModel}}{{/parcelizeModels}}{{/parent}}
{{#vendorExtensions.x-has-data-class-body}}
{
{{/vendorExtensions.x-has-data-class-body}}
{{#hasEnums}}
{{#vars}}
{{#isEnum}}
/**
* {{{description}}}
* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}}
*/
enum class {{{nameInPascalCase}}}(val value: {{{dataType}}}){
{{#allowableValues}}
{{#enumVars}}
{{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
{{/enumVars}}
{{/allowableValues}}
}
{{/isEnum}}
{{/vars}}
{{/hasEnums}}
{{#vendorExtensions.x-has-data-class-body}}
}
{{/vendorExtensions.x-has-data-class-body}}
{{/discriminator}}
{{/isKtor}}

View File

@@ -1,4 +0,0 @@
{{#description}}
/* {{{.}}} */
{{/description}}
open val {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{^isNullable}}{{^required}}?{{/required}}{{/isNullable}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}{{^defaultValue}}{{^required}} = null{{/required}}{{/defaultValue}}

View File

@@ -1,6 +0,0 @@
{{#description}}
/* {{{.}}} */
{{/description}}
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}
@field:com.fasterxml.jackson.annotation.JsonProperty("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
open {{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}

View File

@@ -3,4 +3,4 @@
{{/description}}
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}
@field:com.fasterxml.jackson.annotation.JsonProperty("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
{{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{{defaultValue}}}{{^defaultValue}}null{{/defaultValue}}
{{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{{defaultValue}}}{{^defaultValue}}null{{/defaultValue}}

View File

@@ -3,4 +3,4 @@
{{/description}}
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}
@field:com.fasterxml.jackson.annotation.JsonProperty("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
{{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}
{{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}

View File

@@ -1,6 +0,0 @@
{{#description}}
/* {{{.}}} */
{{/description}}
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}
@field:com.fasterxml.jackson.annotation.JsonProperty("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
open {{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}

View File

@@ -1,5 +0,0 @@
{{#description}}
/* {{{.}}} */
{{/description}}
@get:com.fasterxml.jackson.annotation.JsonProperty("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
open val {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{^isNullable}}{{^required}}?{{/required}}{{/isNullable}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}{{^defaultValue}}{{^required}} = null{{/required}}{{/defaultValue}}

View File

@@ -3,4 +3,4 @@
{{/description}}
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}
@field:com.fasterxml.jackson.annotation.JsonProperty("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
{{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{{defaultValue}}}{{^defaultValue}}null{{/defaultValue}}
{{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{{defaultValue}}}{{^defaultValue}}null{{/defaultValue}}

View File

@@ -3,4 +3,4 @@
{{/description}}
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}
@field:com.fasterxml.jackson.annotation.JsonProperty("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
{{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}
{{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}

View File

@@ -1,6 +0,0 @@
{{#description}}
/* {{{.}}} */
{{/description}}
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}
@field:com.fasterxml.jackson.annotation.JsonProperty("{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}")
open {{>modelMutable}} {{{name}}}: {{#isEnum}}{{{classname}}}.{{{nameInPascalCase}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{{dataType}}}("{{{defaultValue}}}"){{/isNumber}}{{/defaultValue}}

View File

@@ -1,6 +0,0 @@
@com.fasterxml.jackson.annotation.JsonTypeInfo(use = com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME, include = com.fasterxml.jackson.annotation.JsonTypeInfo.As.PROPERTY, property = "{{{discriminator.propertyBaseName}}}", visible = {{#vendorExtensions.x-discriminator-visible-true}}true{{/vendorExtensions.x-discriminator-visible-true}}{{^vendorExtensions.x-discriminator-visible-true}}false{{/vendorExtensions.x-discriminator-visible-true}})
@com.fasterxml.jackson.annotation.JsonSubTypes(
{{#discriminator.mappedModels}}
com.fasterxml.jackson.annotation.JsonSubTypes.Type(value = {{modelName}}::class, name = "{{^vendorExtensions.x-discriminator-value}}{{mappingName}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"){{^-last}},{{/-last}}
{{/discriminator.mappedModels}}
)

View File

@@ -86,8 +86,7 @@ class {{classname}}Controller({{#serviceInterface}}@Autowired(required = true) v
value = [{{#responses}}ApiResponse(code = {{{code}}}, message = "{{{message}}}"{{#baseType}}, response = {{{.}}}::class{{/baseType}}{{#containerType}}, responseContainer = "{{{.}}}"{{/containerType}}){{^-last}},{{/-last}}{{/responses}}]){{/swagger1AnnotationLibrary}}
@RequestMapping(
method = [RequestMethod.{{httpMethod}}],
// "{{#lambdaEscapeInNormalString}}{{{path}}}{{/lambdaEscapeInNormalString}}"
value = [PATH_{{#lambda.uppercase}}{{#lambda.snakecase}}{{{operationId}}}{{/lambda.snakecase}}{{/lambda.uppercase}}]{{#singleContentTypes}}{{#hasProduces}},
value = [PATH_{{#lambda.uppercase}}{{#lambda.snakecase}}{{{operationId}}}{{/lambda.snakecase}}{{/lambda.uppercase}} /* "{{#lambdaEscapeInNormalString}}{{{path}}}{{/lambdaEscapeInNormalString}}" */]{{#singleContentTypes}}{{#hasProduces}},
produces = [{{#vendorExtensions.x-accepts}}"{{{.}}}"{{^-last}}, {{/-last}}{{/vendorExtensions.x-accepts}}]{{/hasProduces}}{{#hasConsumes}},
consumes = "{{{vendorExtensions.x-content-type}}}"{{/hasConsumes}}{{/singleContentTypes}}{{^singleContentTypes}}{{#hasProduces}},
produces = [{{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}}]{{/hasProduces}}{{#hasConsumes}},

View File

@@ -101,8 +101,7 @@ interface {{classname}} {
){{/swagger1AnnotationLibrary}}
@RequestMapping(
method = [RequestMethod.{{httpMethod}}],
// "{{#lambdaEscapeInNormalString}}{{{path}}}{{/lambdaEscapeInNormalString}}"
value = [PATH_{{#lambda.uppercase}}{{#lambda.snakecase}}{{{operationId}}}{{/lambda.snakecase}}{{/lambda.uppercase}}]{{#singleContentTypes}}{{#hasProduces}},
value = [PATH_{{#lambda.uppercase}}{{#lambda.snakecase}}{{{operationId}}}{{/lambda.snakecase}}{{/lambda.uppercase}} /* "{{#lambdaEscapeInNormalString}}{{{path}}}{{/lambdaEscapeInNormalString}}" */]{{#singleContentTypes}}{{#hasProduces}},
produces = [{{#vendorExtensions.x-accepts}}"{{{.}}}"{{^-last}}, {{/-last}}{{/vendorExtensions.x-accepts}}]{{/hasProduces}}{{#hasConsumes}},
consumes = "{{{vendorExtensions.x-content-type}}}"{{/hasConsumes}}{{/singleContentTypes}}{{^singleContentTypes}}{{#hasProduces}},
produces = [{{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}}]{{/hasProduces}}{{#hasConsumes}},

View File

@@ -19,13 +19,31 @@
{{/-last}}{{/optionalVars}}
){{/discriminator}}{{! no newline
}}{{#parent}} : {{{.}}}{{#isMap}}(){{/isMap}}{{! no newline
}}{{#vendorExtensions.x-kotlin-implements}}, {{{.}}}{{/vendorExtensions.x-kotlin-implements}}{{! <- serializableModel is also handled via x-kotlin-implements
}}{{#serializableModel}}{{! no newline
}}{{^vendorExtensions.x-kotlin-implements}}, Serializable{{/vendorExtensions.x-kotlin-implements}}{{! no newline
}}{{#vendorExtensions.x-kotlin-implements}}, Serializable, {{! no newline
}}{{#-first}} {{{.}}}{{/-first}}{{! no newline
}}{{^-first}}, {{{.}}}{{/-first}}{{! no newline
}}{{/vendorExtensions.x-kotlin-implements}}{{! no newline
}}{{/serializableModel}}{{! no newline
}}{{^serializableModel}}{{! no newline
}}{{#vendorExtensions.x-kotlin-implements}}, {{{.}}}{{/vendorExtensions.x-kotlin-implements}}{{! no newline
}}{{/serializableModel}}{{! no newline
}}{{/parent}}{{! no newline
}}{{^parent}}{{! no newline
}}{{#serializableModel}}{{! no newline
}}{{^vendorExtensions.x-kotlin-implements}} : Serializable{{/vendorExtensions.x-kotlin-implements}}{{! no newline
}}{{#vendorExtensions.x-kotlin-implements}}{{! no newline
}}{{#-first}} : Serializable, {{{.}}}{{/-first}}{{! no newline
}}{{^-first}}, {{{.}}}{{/-first}}{{! no newline
}}{{/vendorExtensions.x-kotlin-implements}}{{! no newline
}}{{/serializableModel}}{{! no newline
}}{{^serializableModel}}{{! no newline
}}{{#vendorExtensions.x-kotlin-implements}}{{! no newline
}}{{#-first}} : {{{.}}}{{/-first}}{{! no newline
}}{{^-first}}, {{{.}}}{{/-first}}{{! no newline
}}{{/vendorExtensions.x-kotlin-implements}}{{! no newline
}}{{/serializableModel}}{{! no newline
}}{{/parent}} {
{{#discriminator}}
{{#requiredVars}}

View File

@@ -6,9 +6,6 @@ package {{package}}
{{#imports}}import {{import}}
{{/imports}}
{{#useRequestMappingOnInterface}}
import {{#apiPackage}}{{.}}.{{/apiPackage}}{{classname}}.Companion.BASE_PATH
{{/useRequestMappingOnInterface}}
{{#swagger2AnnotationLibrary}}
import io.swagger.v3.oas.annotations.*
@@ -51,7 +48,7 @@ import kotlin.collections.List
import kotlin.collections.Map
{{#useRequestMappingOnInterface}}
@HttpExchange(BASE_PATH) // Generate with 'requestMappingMode' set to 'none' to skip the base path on the interface
@HttpExchange("\${api.base-path:{{contextPath}}}")
{{/useRequestMappingOnInterface}}
{{#useBeanValidation}}
@Validated
@@ -63,8 +60,7 @@ interface {{classname}} {
}}{{^useResponseEntity}} @ResponseStatus({{#springHttpStatus}}{{#responses.0}}{{{code}}}{{/responses.0}}{{/springHttpStatus}})
{{/useResponseEntity}}{{!
}}{{#httpMethod}} @HttpExchange(
// "{{#lambdaEscapeInNormalString}}{{{path}}}{{/lambdaEscapeInNormalString}}"
url = PATH_{{#lambda.uppercase}}{{#lambda.snakecase}}{{{operationId}}}{{/lambda.snakecase}}{{/lambda.uppercase}},
url = PATH_{{#lambda.uppercase}}{{#lambda.snakecase}}{{{operationId}}}{{/lambda.snakecase}}{{/lambda.uppercase}} /* "{{#lambdaEscapeInNormalString}}{{{path}}}{{/lambdaEscapeInNormalString}}" */,
method = "{{httpMethod}}"
)
{{/httpMethod}}{{!
@@ -78,7 +74,9 @@ interface {{classname}} {
{{/operation}}
companion object {
//for your own safety never directly reuse these path definitions in tests
{{#useRequestMappingOnInterface}}
const val BASE_PATH: String = "{{=<% %>=}}<%contextPath%><%={{ }}=%>"
{{/useRequestMappingOnInterface}}
{{#operation}}
const val PATH_{{#lambda.uppercase}}{{#lambda.snakecase}}{{{operationId}}}{{/lambda.snakecase}}{{/lambda.uppercase}}: String = "{{{path}}}"
{{/operation}}

View File

@@ -3,6 +3,9 @@ package {{package}}
import java.util.Objects
{{#imports}}import {{import}}
{{/imports}}
{{#serializableModel}}
import java.io.Serializable
{{/serializableModel}}
{{#useBeanValidation}}
import {{javaxPackage}}.validation.constraints.DecimalMax
import {{javaxPackage}}.validation.constraints.DecimalMin

View File

@@ -68,20 +68,7 @@ class RESTClientObject:
self.proxy = configuration.proxy
self.proxy_headers = configuration.proxy_headers
retries = configuration.retries
if retries is None:
self._effective_retry_options = None
elif isinstance(retries, aiohttp_retry.RetryOptionsBase):
self._effective_retry_options = retries
elif isinstance(retries, int):
self._effective_retry_options = aiohttp_retry.ExponentialRetry(
attempts=retries,
factor=2.0,
start_timeout=0.1,
max_timeout=120.0
)
else:
self._effective_retry_options = None
self.retries = configuration.retries
self.pool_manager: Optional[aiohttp.ClientSession] = None
self.retry_client: Optional[aiohttp_retry.RetryClient] = None
@@ -204,11 +191,16 @@ class RESTClientObject:
)
pool_manager = self.pool_manager
if self._effective_retry_options is not None and method in ALLOW_RETRY_METHODS:
if self.retries is not None and method in ALLOW_RETRY_METHODS:
if self.retry_client is None:
self.retry_client = aiohttp_retry.RetryClient(
client_session=self.pool_manager,
retry_options=self._effective_retry_options
retry_options=aiohttp_retry.ExponentialRetry(
attempts=self.retries,
factor=2.0,
start_timeout=0.1,
max_timeout=120.0
)
)
pool_manager = self.retry_client

View File

@@ -188,12 +188,7 @@ class Configuration:
values before.
:param ssl_ca_cert: str - the path to a file of concatenated CA certificates
in PEM format.
{{#async}}
:param retries: int | aiohttp_retry.RetryOptionsBase - Retry configuration.
{{/async}}
{{^async}}
:param retries: int | urllib3.util.retry.Retry - Retry configuration.
{{/async}}
:param retries: Number of retries for API requests.
:param ca_cert_data: verify the peer using concatenated CA certificate data
in PEM (str) or DER (bytes) format.
:param cert_file: the path to a client certificate file, for mTLS.
@@ -303,7 +298,7 @@ conf = {{{packageName}}}.Configuration(
server_operation_variables: Optional[Dict[int, ServerVariablesT]]=None,
ignore_operation_servers: bool=False,
ssl_ca_cert: Optional[str]=None,
retries: Optional[Union[int, Any]] = None,
retries: Optional[int] = None,
ca_cert_data: Optional[Union[str, bytes]] = None,
cert_file: Optional[str]=None,
key_file: Optional[str]=None,
@@ -437,7 +432,7 @@ conf = {{{packageName}}}.Configuration(
"""Safe chars for path_param
"""
self.retries = retries
"""Retry configuration
"""Adding retries to override urllib3 default value 3
"""
# Enable client side validation
self.client_side_validation = True

View File

@@ -71,7 +71,7 @@
"es6-promise": "^4.2.4"
},
"devDependencies": {
"typescript": "^{{typescriptMajorVersion}}.0"
"typescript": "^4.0"
}{{#npmRepository}},{{/npmRepository}}
{{#npmRepository}}
"publishConfig":{

View File

@@ -3769,35 +3769,6 @@ public class JavaClientCodegenTest {
);
}
@Test
public void testRequiredAndNullableAreBothTrue() throws IOException {
File output = Files.createTempDirectory("test").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("java")
.setLibrary(JavaClientCodegen.OKHTTP_GSON)
.setInputSpec("src/test/resources/bugs/issue_18516.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
files.forEach(File::deleteOnExit);
validateJavaSourceFiles(files);
Path modelFile = Paths.get(output + "/src/main/java/org/openapitools/client/model/SomeObject.java");
TestUtils.assertFileContains(
modelFile,
"} else if (!jsonObj.get(\"ids\").isJsonArray() && !jsonObj.get(\"ids\").isJsonNull()) {",
"if (jsonObj.get(\"users\") != null && !jsonObj.get(\"users\").isJsonNull()) {",
"if (!jsonObj.get(\"users\").isJsonArray()) {",
"if (jsonObj.get(\"user\") != null && !jsonObj.get(\"user\").isJsonNull()) {",
"if (jsonObj.get(\"role\") != null && !jsonObj.get(\"role\").isJsonNull()) {",
"if (jsonObj.get(\"custom\") != null && !jsonObj.get(\"custom\").isJsonNull()) {");
}
@Test(description = "Issue #21051")
public void givenComplexObjectHasDefaultValueWhenGenerateThenDefaultAssignmentsAreValid() throws Exception {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();

View File

@@ -5,7 +5,6 @@ import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.*;
import com.github.javaparser.ast.nodeTypes.NodeWithName;
import com.github.javaparser.ast.nodeTypes.modifiers.NodeWithAbstractModifier;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import org.assertj.core.api.AbstractAssert;
import org.assertj.core.api.Assertions;
import org.assertj.core.util.CanIgnoreReturnValue;
@@ -16,9 +15,7 @@ import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@CanIgnoreReturnValue
public class JavaFileAssert extends AbstractAssert<JavaFileAssert, CompilationUnit> {
@@ -59,36 +56,6 @@ public class JavaFileAssert extends AbstractAssert<JavaFileAssert, CompilationUn
return this;
}
public JavaFileAssert implementsInterfaces(String... implementedInterfaces) {
Set<String> expectedInterfaces = Stream.of(implementedInterfaces)
.collect(Collectors.toSet());
Set<String> actualInterfaces = actual.getType(0)
.asClassOrInterfaceDeclaration()
.getImplementedTypes().stream()
.map(ClassOrInterfaceType::getNameWithScope)
.collect(Collectors.toSet());
Assertions.assertThat(actualInterfaces)
.withFailMessage("Expected type %s to implement interfaces %s, but found %s",
actual.getType(0).getName().asString(), expectedInterfaces, actualInterfaces)
.isEqualTo(expectedInterfaces);
return this;
}
public JavaFileAssert doesNotImplementInterfaces(String... interfaces) {
Set<String> forbiddenInterfaces = Stream.of(interfaces).collect(Collectors.toSet());
Set<String> implemented = actual.getType(0).asClassOrInterfaceDeclaration()
.getImplementedTypes().stream()
.map(ClassOrInterfaceType::getNameWithScope)
.collect(Collectors.toSet());
Assertions.assertThat(implemented)
.withFailMessage("Expected type %s to not implement interfaces %s, but found %s",
actual.getType(0).getName().asString(), forbiddenInterfaces, implemented)
.doesNotContainAnyElementsOf(forbiddenInterfaces);
return this;
}
public JavaFileAssert isAbstractClass() {
Assertions.assertThat(actual.getType(0).asClassOrInterfaceDeclaration())
.withFailMessage("Expected type %s to be an abstract class", actual.getType(0).getName().asString())

Some files were not shown because too many files have changed in this diff Show More