diff --git a/.github/workflows/check-supported-versions.yaml b/.github/workflows/check-supported-versions.yaml
index 35c95b5b2aa..430b0ea815c 100644
--- a/.github/workflows/check-supported-versions.yaml
+++ b/.github/workflows/check-supported-versions.yaml
@@ -24,18 +24,18 @@ jobs:
uses: actions/checkout@v2
- name: Set up JDK ${{ matrix.java }}
- uses: actions/setup-java@v1
+ uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java }}
- - uses: actions/cache@v2.1.4
+ - uses: actions/cache@v2.1.5
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('pom.xml', 'modules/**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- - uses: actions/cache@v2.1.4
+ - uses: actions/cache@v2.1.5
with:
path: |
~/.gradle/caches
@@ -49,7 +49,7 @@ jobs:
run: mvn -nsu -B --quiet -Djacoco.skip=true -Dorg.slf4j.simpleLogger.defaultLogLevel=error --no-transfer-progress clean install --file pom.xml ${{ matrix.flags }}
- name: Upload Maven build artifact
- uses: actions/upload-artifact@v2.2.2
+ uses: actions/upload-artifact@v2.2.3
if: matrix.java == '8' && matrix.os == 'ubuntu-latest'
with:
name: artifact
diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml
index bc4992833b7..98f191f2c9c 100644
--- a/.github/workflows/sonar.yml
+++ b/.github/workflows/sonar.yml
@@ -14,7 +14,7 @@ jobs:
steps:
- uses: actions/checkout@v1
- name: Set up JDK 11
- uses: actions/setup-java@v1
+ uses: actions/setup-java@v2
with:
java-version: 11
- name: Compile with Maven
diff --git a/.travis.yml b/.travis.yml
index 9ba0b842f02..cc1f953acaa 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -62,6 +62,14 @@ addons:
- petstore.swagger.io
before_install:
+ - sudo rm -rf /var/lib/apt/lists/*
+ - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
+ - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) edge"
+ - sudo apt-get update
+ - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
+ - mkdir -vp ~/.docker/cli-plugins/
+ - curl --silent -L "https://github.com/docker/buildx/releases/download/v0.3.0/buildx-v0.3.0.linux-amd64" > ~/.docker/cli-plugins/docker-buildx
+ - chmod a+x ~/.docker/cli-plugins/docker-buildx
# to run petstore server locally via docker
- echo "$DOCKER_HUB_PASSWORD" | docker login --username=$DOCKER_HUB_USERNAME --password-stdin || true
- docker pull swaggerapi/petstore
@@ -149,6 +157,8 @@ install:
script:
# fail fast
- set -e
+ # show docker buildx version
+ - docker buildx version
# fail if the template files contains tabs
- /bin/bash ./bin/utils/detect_tab_in_templates.sh
# fail if the test files have changes
@@ -199,12 +209,14 @@ after_success:
echo "$DOCKER_HUB_PASSWORD" | docker login --username=$DOCKER_HUB_USERNAME --password-stdin;
export cli_version=$(\mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\[');
export build_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ");
- docker build --label=org.opencontainers.image.created=$build_date --label=org.opencontainers.image.title=openapi-generator-online --label=org.opencontainers.image.revision=$TRAVIS_COMMIT --label=org.opencontainers.image.version=$cli_version -t $DOCKER_GENERATOR_IMAGE_NAME ./modules/openapi-generator-online;
+ docker buildx create --use;
if [ ! -z "$TRAVIS_TAG" ]; then
- docker tag $DOCKER_GENERATOR_IMAGE_NAME:latest $DOCKER_GENERATOR_IMAGE_NAME:$TRAVIS_TAG;
+ docker buildx build --platform linux/amd64,linux/arm64 --label=org.opencontainers.image.created=$build_date --label=org.opencontainers.image.title=openapi-generator-online --label=org.opencontainers.image.revision=$TRAVIS_COMMIT --label=org.opencontainers.image.version=$cli_version -t $DOCKER_GENERATOR_IMAGE_NAME:latest -t $DOCKER_GENERATOR_IMAGE_NAME:$TRAVIS_TAG -t $DOCKER_GENERATOR_IMAGE_NAME ./modules/openapi-generator-online;
+ echo "Built and tagged $DOCKER_GENERATOR_IMAGE_NAME";
fi;
- if [ ! -z "$TRAVIS_TAG" ] || [ "$TRAVIS_BRANCH" = "master" ]; then
- docker push $DOCKER_GENERATOR_IMAGE_NAME && echo "Pushed to $DOCKER_GENERATOR_IMAGE_NAME";
+ if [ -z "$TRAVIS_TAG" ] && [ "$TRAVIS_BRANCH" = "master" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
+ docker buildx build --push --platform linux/amd64,linux/arm64 --label=org.opencontainers.image.created=$build_date --label=org.opencontainers.image.title=openapi-generator-online --label=org.opencontainers.image.revision=$TRAVIS_COMMIT --label=org.opencontainers.image.version=$cli_version -t $DOCKER_GENERATOR_IMAGE_NAME ./modules/openapi-generator-online;
+ echo "Pushed to $DOCKER_GENERATOR_IMAGE_NAME for master";
fi;
fi;
## docker: build cli image and push to Docker Hub
@@ -213,12 +225,14 @@ after_success:
cp docker-entrypoint.sh ./modules/openapi-generator-cli;
export cli_version=$(\mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\[');
export build_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ");
- docker build --label=org.opencontainers.image.created=$build_date --label=org.opencontainers.image.title=openapi-generator-cli --label=org.opencontainers.image.revision=$TRAVIS_COMMIT --label=org.opencontainers.image.version=$cli_version -t $DOCKER_CODEGEN_CLI_IMAGE_NAME ./modules/openapi-generator-cli;
+ docker buildx create --use;
+ docker buildx build --platform linux/amd64,linux/arm64 --label=org.opencontainers.image.created=$build_date --label=org.opencontainers.image.title=openapi-generator-cli --label=org.opencontainers.image.revision=$TRAVIS_COMMIT --label=org.opencontainers.image.version=$cli_version -t $DOCKER_CODEGEN_CLI_IMAGE_NAME ./modules/openapi-generator-cli;
if [ ! -z "$TRAVIS_TAG" ]; then
- docker tag $DOCKER_CODEGEN_CLI_IMAGE_NAME:latest $DOCKER_CODEGEN_CLI_IMAGE_NAME:$TRAVIS_TAG;
+ docker buildx build --platform linux/amd64,linux/arm64 --label=org.opencontainers.image.created=$build_date --label=org.opencontainers.image.title=openapi-generator-cli --label=org.opencontainers.image.revision=$TRAVIS_COMMIT --label=org.opencontainers.image.version=$cli_version -t $DOCKER_CODEGEN_CLI_IMAGE_NAME:latest -t $DOCKER_CODEGEN_CLI_IMAGE_NAME:$TRAVIS_TAG -t $DOCKER_CODEGEN_CLI_IMAGE_NAME ./modules/openapi-generator-cli;
+ echo "Built and tagged $DOCKER_GENERATOR_IMAGE_NAME";
fi;
- if [ ! -z "$TRAVIS_TAG" ] || [ "$TRAVIS_BRANCH" = "master" ]; then
- docker push $DOCKER_CODEGEN_CLI_IMAGE_NAME;
+ if [ -z "$TRAVIS_TAG" ] && [ "$TRAVIS_BRANCH" = "master" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
+ docker buildx build --push --platform linux/amd64,linux/arm64 --label=org.opencontainers.image.created=$build_date --label=org.opencontainers.image.title=openapi-generator-cli --label=org.opencontainers.image.revision=$TRAVIS_COMMIT --label=org.opencontainers.image.version=$cli_version -t $DOCKER_CODEGEN_CLI_IMAGE_NAME ./modules/openapi-generator-cli;
echo "Pushed to $DOCKER_CODEGEN_CLI_IMAGE_NAME";
fi;
fi;
diff --git a/CI/.drone.yml b/CI/.drone.yml
index 49495e43094..037fb654724 100644
--- a/CI/.drone.yml
+++ b/CI/.drone.yml
@@ -2,6 +2,22 @@ kind: pipeline
name: default
steps:
+# test Java 11 HTTP client
+- name: java11-test
+ image: openjdk:11.0
+ commands:
+ - ./mvnw --quiet clean install -Dorg.slf4j.simpleLogger.defaultLogLevel=error
+ - ./mvnw --quiet verify -Psamples.droneio -Dorg.slf4j.simpleLogger.defaultLogLevel=error
+ # run ensure up-to-date
+ - /bin/bash bin/utils/ensure-up-to-date
+ # test java native client
+ - ./mvnw clean test -f samples/client/petstore/java/native/pom.xml
+ - ./mvnw clean test -f samples/client/petstore/java/native-async/pom.xml
+ - ./mvnw clean test -f samples/openapi3/client/petstore/java/native/pom.xml
+ # test all generators with fake petstore spec (2.0, 3.0)
+ - /bin/bash bin/utils/test-fake-petstore-for-all.sh
+ # generate test scripts
+ - /bin/bash bin/tests/run-all-test
# test nim client
- name: nim-client-test
image: nimlang/nim
@@ -38,21 +54,3 @@ steps:
image: haskell:8.6.5
commands:
- (cd samples/client/petstore/haskell-http-client/ && stack --install-ghc --no-haddock-deps haddock --fast && stack test --fast)
-# test Java 11 HTTP client
-- name: java11-test
- image: openjdk:11.0
- commands:
- - ./mvnw --quiet clean install -Dorg.slf4j.simpleLogger.defaultLogLevel=error
- - ./mvnw --quiet verify -Psamples.droneio -Dorg.slf4j.simpleLogger.defaultLogLevel=error
- # test java native client
- - ./mvnw clean test -f samples/client/petstore/java/native/pom.xml
- - ./mvnw clean test -f samples/client/petstore/java/native-async/pom.xml
- - ./mvnw clean test -f samples/openapi3/client/petstore/java/native/pom.xml
- # test all generators with fake petstore spec (2.0, 3.0)
- - /bin/bash bin/utils/test-fake-petstore-for-all.sh
- # generate test scripts
- - /bin/bash bin/tests/run-all-test
- # generate all petstore samples (client, servers, doc)
- - /bin/bash bin/generate-samples.sh
- # generate all petstore samples (openapi3)
- - /bin/bash bin/generate-samples.sh bin/configs/other/*.yaml
diff --git a/CI/circle_parallel.sh b/CI/circle_parallel.sh
index b8d25329014..b647131c7d7 100755
--- a/CI/circle_parallel.sh
+++ b/CI/circle_parallel.sh
@@ -23,7 +23,6 @@ function installDart {
sudo apt-get update
sudo apt-get install dart
export PATH="$PATH:/usr/lib/dart/bin"
- export DART_POST_PROCESS="dart format"
}
if [ "$NODE_INDEX" = "1" ]; then
@@ -48,7 +47,8 @@ elif [ "$NODE_INDEX" = "2" ]; then
git checkout -- .
# look for outdated samples
- ./bin/utils/ensure-up-to-date
+ #./bin/utils/ensure-up-to-date
+ # UPDATE: moved to drone.io
fi
echo "Running node $NODE_INDEX to test haskell"
# install haskell
diff --git a/README.md b/README.md
index 5b36ced7376..c27f86b1531 100644
--- a/README.md
+++ b/README.md
@@ -78,7 +78,7 @@ OpenAPI Generator allows generation of API client libraries (SDK generation), se
| | Languages/Frameworks |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **API clients** | **ActionScript**, **Ada**, **Apex**, **Bash**, **C**, **C#** (.net 2.0, 3.5 or later, .NET Standard 1.3 - 2.0, .NET Core 2.0, .NET 5.0. Libraries: RestSharp, HttpClient), **C++** (cpp-restsdk, Qt5, Tizen, Unreal Engine 4), **Clojure**, **Crystal**, **Dart**, **Elixir**, **Elm**, **Eiffel**, **Erlang**, **Go**, **Groovy**, **Haskell** (http-client, Servant), **Java** (Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx, Google API Client Library for Java, Rest-assured, Spring 5 Web Client, MicroProfile Rest Client), **k6**, **Kotlin**, **Lua**, **Nim**, **Node.js/JavaScript** (ES5, ES6, AngularJS with Google Closure Compiler annotations, Flow types, Apollo GraphQL DataStore), **Objective-C**, **OCaml**, **Perl**, **PHP**, **PowerShell**, **Python**, **R**, **Ruby**, **Rust** (hyper, reqwest, rust-server), **Scala** (akka, http4s, scalaz, sttp, swagger-async-httpclient), **Swift** (2.x, 3.x, 4.x, 5.x), **Typescript** (AngularJS, Angular (2.x - 11.x), Aurelia, Axios, Fetch, Inversify, jQuery, Nestjs, Node, redux-query, Rxjs) |
-| **Server stubs** | **Ada**, **C#** (ASP.NET Core, NancyFx), **C++** (Pistache, Restbed, Qt5 QHTTPEngine), **Erlang**, **F#** (Giraffe), **Go** (net/http, Gin), **Haskell** (Servant), **Java** (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, Jersey, RestEasy, Play Framework, [PKMST](https://github.com/ProKarma-Inc/pkmst-getting-started-examples), [Vert.x](https://vertx.io/)), **Kotlin** (Spring Boot, Ktor, Vertx), **PHP** (Laravel, Lumen, Slim, Silex, [Symfony](https://symfony.com/), [Zend Expressive](https://github.com/zendframework/zend-expressive)), **Python** (Flask), **NodeJS**, **Ruby** (Sinatra, Rails5), **Rust** (rust-server), **Scala** (Akka, [Finch](https://github.com/finagle/finch), [Lagom](https://github.com/lagom/lagom), [Play](https://www.playframework.com/), Scalatra) |
+| **Server stubs** | **Ada**, **C#** (ASP.NET Core, NancyFx), **C++** (Pistache, Restbed, Qt5 QHTTPEngine), **Erlang**, **F#** (Giraffe), **Go** (net/http, Gin, Echo), **Haskell** (Servant), **Java** (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, Jersey, RestEasy, Play Framework, [PKMST](https://github.com/ProKarma-Inc/pkmst-getting-started-examples), [Vert.x](https://vertx.io/)), **Kotlin** (Spring Boot, Ktor, Vertx), **PHP** (Laravel, Lumen, Slim, Silex, [Symfony](https://symfony.com/), [Zend Expressive](https://github.com/zendframework/zend-expressive)), **Python** (Flask), **NodeJS**, **Ruby** (Sinatra, Rails5), **Rust** (rust-server), **Scala** (Akka, [Finch](https://github.com/finagle/finch), [Lagom](https://github.com/lagom/lagom), [Play](https://www.playframework.com/), Scalatra) |
| **API documentation generators** | **HTML**, **Confluence Wiki**, **Asciidoc**, **Markdown**, **PlantUML** |
| **Configuration files** | [**Apache2**](https://httpd.apache.org/) |
| **Others** | **GraphQL**, **JMeter**, **Ktorm**, **MySQL Schema**, **Protocol Buffer** |
@@ -659,6 +659,7 @@ Here are some companies/projects (alphabetical order) using OpenAPI Generator in
- [Stingray](http://www.stingray.com)
- [Suva](https://www.suva.ch/)
- [Telstra](https://dev.telstra.com)
+- [The University of Aizu](https://www.u-aizu.ac.jp/en/)
- [TravelTime platform](https://www.traveltimeplatform.com/)
- [TribalScale](https://www.tribalscale.com)
- [TUI InfoTec GmbH](http://www.tui-infotec.com/)
@@ -814,6 +815,14 @@ Here are some companies/projects (alphabetical order) using OpenAPI Generator in
- 2021-01-18 - [「アプリ開発あるある」を疑うことから始まった、API Clientコードの自動生成【デブスト2020】](https://codezine.jp/article/detail/13406?p=2) by [CodeZine編集部](https://codezine.jp/author/1)
- 2021-02-05 - [REST-API-Roundtrip with SpringDoc and OpenAPI Generator](https://blog.viadee.de/en/rest-api-roundtrip) by [Benjamin Klatt](https://twitter.com/benklatt) at [viadee](https://www.viadee.de/en/)
- 2021-02-17 - [REST-API-Roundtrip with SpringDoc and OpenAPI Generator](https://medium.com/nerd-for-tech/rest-api-roundtrip-with-springdoc-and-openapi-generator-30bd27ccf698) by [cloud @viadee](https://cloud-viadee.medium.com/)
+- 2021-03-08 - [OpenAPI Generator 工具的躺坑尝试](https://blog.csdn.net/u013019701/article/details/114531975) by [独家雨天](https://blog.csdn.net/u013019701) at [CSDN官方博客](https://blog.csdn.net/)
+- 2021-03-16 - [如何基于 Swagger 使用 OpenAPI Generator 生成 JMeter 脚本?](https://cloud.tencent.com/developer/article/1802704) by [高楼Zee](https://cloud.tencent.com/developer/user/5836255) at [腾讯云专栏](https://cloud.tencent.com/developer/column)
+- 2021-03-24 - [openapi-generator-cli による TypeScript 型定義](https://zenn.dev/takepepe/articles/openapi-generator-cli-ts) by [Takefumi Yoshii](https://zenn.dev/takepepe)
+- 2021-03-28 - [Trying out NestJS part 4: Generate Typescript clients from OpenAPI documents](https://dev.to/arnaudcortisse/trying-out-nestjs-part-4-generate-typescript-clients-from-openapi-documents-28mk) by [Arnaud Cortisse](https://dev.to/arnaudcortisse)
+- 2021-03-31 - [Open API Server Implementation Using OpenAPI Generator](https://www.baeldung.com/java-openapi-generator-server) at [Baeldung](https://www.baeldung.com/)
+- 2021-03-31 - [使用OpenAPI Generator實現Open API Server](https://www.1ju.org/article/java-openapi-generator-server) at [億聚網](https://www.1ju.org/)
+- 2022-04-19 - [Introducing Twilio’s OpenAPI Specification Beta](https://www.twilio.com/blog/introducing-twilio-open-api-specification-beta) by [GARETH PAUL JONES](https://www.twilio.com/blog/author/gpj) at [Twilio Blog](https://www.twilio.com/blog)
+- 2022-04-22 - [Leveraging OpenApi strengths in a Micro-Service environment](https://medium.com/unibuddy-technology-blog/leveraging-openapi-strengths-in-a-micro-service-environment-3d7f9e7c26ff) by Nicolas Jellab at [Unibuddy Technology Blog](https://medium.com/unibuddy-technology-blog)
## [6 - About Us](#table-of-contents)
@@ -926,6 +935,7 @@ Here is a list of template creators:
* Erlang Server: @galaxie
* F# (Giraffe) Server: @nmfisher
* Go Server: @guohuang
+ * Go (Echo) Server: @ph4r5h4d
* Go (Gin) Server: @kemokemo
* GraphQL Express Server: @renepardon
* Haskell Servant: @algas
@@ -1018,7 +1028,7 @@ If you want to join the committee, please kindly apply by sending an email to te
| Elm | @eriktim (2018/09) |
| Erlang | @tsloughter (2017/11) @jfacorro (2018/10) @robertoaloi (2018/10) |
| F# | @nmfisher (2019/05) |
-| Go | @antihax (2017/11) @grokify (2018/07) @kemokemo (2018/09) @jirikuncar (2021/01) |
+| Go | @antihax (2017/11) @grokify (2018/07) @kemokemo (2018/09) @jirikuncar (2021/01) @ph4r5h4d (2021/04) |
| GraphQL | @renepardon (2018/12) |
| Groovy | |
| Haskell | |
diff --git a/appveyor.yml b/appveyor.yml
index b5fe251f30a..ec69f197198 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -43,6 +43,8 @@ build_script:
- dotnet build samples\server\petstore\aspnetcore-3.0\Org.OpenAPITools.sln
# build C# aspnetcore 2.2 server
- dotnet build samples\server\petstore\aspnetcore\Org.OpenAPITools.sln
+ # build C# API client (multiple frameworks)
+ - dotnet build samples\client\petstore\csharp-netcore\OpenAPIClientCoreAndNet47\Org.OpenAPITools.sln
# build C# API client (httpclient)
- dotnet build samples\client\petstore\csharp-netcore\OpenAPIClient-httpclient\Org.OpenAPITools.sln
# build C# API client (netcore)
@@ -66,6 +68,8 @@ build_script:
# run the locally installed openapi-generator-gradle-plugin
- gradle -b modules\openapi-generator-gradle-plugin\samples\local-spec\build.gradle buildGoSdk --stacktrace
test_script:
+ # test c# API client (multiple frameworks)
+ - dotnet test samples\client\petstore\csharp-netcore\OpenAPIClientCoreAndNet47\src\Org.OpenAPITools.Test\Org.OpenAPITools.Test.csproj
# test c# API client (httpclient)
- dotnet test samples\client\petstore\csharp-netcore\OpenAPIClient-httpclient\src\Org.OpenAPITools.Test\Org.OpenAPITools.Test.csproj
# test c# API client (netcore)
diff --git a/bin/configs/other/bash.yaml b/bin/configs/bash.yaml
similarity index 100%
rename from bin/configs/other/bash.yaml
rename to bin/configs/bash.yaml
diff --git a/bin/configs/csharp-netcore-OpenAPIClientCoreAndNet47.yaml b/bin/configs/csharp-netcore-OpenAPIClientCoreAndNet47.yaml
new file mode 100644
index 00000000000..58b30f42acb
--- /dev/null
+++ b/bin/configs/csharp-netcore-OpenAPIClientCoreAndNet47.yaml
@@ -0,0 +1,8 @@
+generatorName: csharp-netcore
+outputDir: samples/client/petstore/csharp-netcore/OpenAPIClientCoreAndNet47
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
+templateDir: modules/openapi-generator/src/main/resources/csharp-netcore
+additionalProperties:
+ packageGuid: '{321C8C3F-0156-40C1-AE42-D59761FB9B6C}'
+ targetFramework: netstandard2.1;netcoreapp3.0
+ useCompareNetObjects: "true"
diff --git a/bin/configs/other/dart-dio-next-petstore-client-lib-fake.yaml b/bin/configs/dart-dio-next-petstore-client-lib-fake.yaml
similarity index 80%
rename from bin/configs/other/dart-dio-next-petstore-client-lib-fake.yaml
rename to bin/configs/dart-dio-next-petstore-client-lib-fake.yaml
index d6a85861a8a..edcc346a19f 100644
--- a/bin/configs/other/dart-dio-next-petstore-client-lib-fake.yaml
+++ b/bin/configs/dart-dio-next-petstore-client-lib-fake.yaml
@@ -2,6 +2,9 @@ generatorName: dart-dio-next
outputDir: samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
templateDir: modules/openapi-generator/src/main/resources/dart/libraries/dio
-enablePostProcessFile: "true"
+typeMappings:
+ Client: "ModelClient"
+ File: "ModelFile"
+ EnumClass: "ModelEnumClass"
additionalProperties:
hideGenerationTimestamp: "true"
diff --git a/bin/configs/dart-dio-petstore-client-lib-fake.yaml b/bin/configs/dart-dio-petstore-client-lib-fake.yaml
index 2463da464ed..eca85edfd88 100644
--- a/bin/configs/dart-dio-petstore-client-lib-fake.yaml
+++ b/bin/configs/dart-dio-petstore-client-lib-fake.yaml
@@ -2,5 +2,9 @@ generatorName: dart-dio
outputDir: samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
templateDir: modules/openapi-generator/src/main/resources/dart-dio
+typeMappings:
+ Client: "ModelClient"
+ File: "ModelFile"
+ EnumClass: "ModelEnumClass"
additionalProperties:
hideGenerationTimestamp: "true"
diff --git a/bin/configs/dart-dio-petstore-client-lib-oas2.yaml b/bin/configs/dart-dio-petstore-client-lib-oas2.yaml
deleted file mode 100644
index 447136518a8..00000000000
--- a/bin/configs/dart-dio-petstore-client-lib-oas2.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-generatorName: dart-dio
-outputDir: samples/client/petstore/dart-dio/petstore_client_lib
-inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
-templateDir: modules/openapi-generator/src/main/resources/dart-dio
-additionalProperties:
- hideGenerationTimestamp: "true"
diff --git a/bin/configs/dart-petstore-client-lib-fake.yaml b/bin/configs/dart-petstore-client-lib-fake.yaml
index 8dda4df4b0a..d48cd8038b7 100644
--- a/bin/configs/dart-petstore-client-lib-fake.yaml
+++ b/bin/configs/dart-petstore-client-lib-fake.yaml
@@ -2,5 +2,8 @@ generatorName: dart
outputDir: samples/openapi3/client/petstore/dart2/petstore_client_lib_fake
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
templateDir: modules/openapi-generator/src/main/resources/dart2
+typeMappings:
+ Client: "ModelClient"
+ File: "ModelFile"
additionalProperties:
hideGenerationTimestamp: "true"
diff --git a/bin/configs/dart-petstore-client-lib-oas2.yaml b/bin/configs/dart-petstore-client-lib-oas2.yaml
deleted file mode 100644
index 861a829ac4f..00000000000
--- a/bin/configs/dart-petstore-client-lib-oas2.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-generatorName: dart
-outputDir: samples/client/petstore/dart2/petstore_client_lib
-inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
-templateDir: modules/openapi-generator/src/main/resources/dart2
-additionalProperties:
- hideGenerationTimestamp: "true"
diff --git a/bin/configs/dart-petstore-json-serializable-client-lib-fake.yaml b/bin/configs/dart-petstore-json-serializable-client-lib-fake.yaml
index cb943d3d957..8582a881d51 100644
--- a/bin/configs/dart-petstore-json-serializable-client-lib-fake.yaml
+++ b/bin/configs/dart-petstore-json-serializable-client-lib-fake.yaml
@@ -2,6 +2,9 @@ generatorName: dart
outputDir: samples/openapi3/client/petstore/dart2/petstore_json_serializable_client_lib_fake
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
templateDir: modules/openapi-generator/src/main/resources/dart2
+typeMappings:
+ Client: "ModelClient"
+ File: "ModelFile"
additionalProperties:
hideGenerationTimestamp: "true"
serializationLibrary: json_serializable
diff --git a/bin/configs/go-echo-server-petstore-new.yaml b/bin/configs/go-echo-server-petstore-new.yaml
new file mode 100644
index 00000000000..bfc2e946c58
--- /dev/null
+++ b/bin/configs/go-echo-server-petstore-new.yaml
@@ -0,0 +1,6 @@
+generatorName: go-echo-server
+outputDir: samples/server/petstore/go-echo-server
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
+templateDir: modules/openapi-generator/src/main/resources/go-echo-server
+additionalProperties:
+ hideGenerationTimestamp: "true"
diff --git a/bin/configs/go-server-go-api-server.yaml b/bin/configs/go-server-go-api-server.yaml
index 6446d212a35..7fb761639b2 100644
--- a/bin/configs/go-server-go-api-server.yaml
+++ b/bin/configs/go-server-go-api-server.yaml
@@ -5,3 +5,4 @@ templateDir: modules/openapi-generator/src/main/resources/go-server
additionalProperties:
hideGenerationTimestamp: "true"
packageName: petstoreserver
+ addResponseHeaders: true
diff --git a/bin/configs/php-symfony-SymfonyBundle-php.yaml b/bin/configs/php-symfony-SymfonyBundle-php.yaml
index c77a71f14b7..f7c6218a50f 100644
--- a/bin/configs/php-symfony-SymfonyBundle-php.yaml
+++ b/bin/configs/php-symfony-SymfonyBundle-php.yaml
@@ -1,4 +1,4 @@
generatorName: php-symfony
outputDir: samples/server/petstore/php-symfony/SymfonyBundle-php
-inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/php-symfony
diff --git a/bin/configs/python-oas2.yaml b/bin/configs/python-oas2.yaml
index 4555376bd16..7c548fb3926 100644
--- a/bin/configs/python-oas2.yaml
+++ b/bin/configs/python-oas2.yaml
@@ -1,7 +1,10 @@
+# this file exists because in this file we omit setting disallowAdditionalPropertiesIfNotPresent
+# which makes it default to false
+# that false setting is needed for composed schemas to work
+# Composed schemas are schemas that contain the allOf/oneOf/anyOf keywords. v2 specs only support the allOf keyword.
generatorName: python
outputDir: samples/client/petstore/python
inputSpec: modules/openapi-generator/src/test/resources/2_0/python-client-experimental/petstore-with-fake-endpoints-models-for-testing.yaml
templateDir: modules/openapi-generator/src/main/resources/python
additionalProperties:
- disallowAdditionalPropertiesIfNotPresent: "true"
packageName: petstore_api
diff --git a/bin/configs/python-oas2_disallowAdditionalPropertiesIfNotPresent.yaml b/bin/configs/python-oas2_disallowAdditionalPropertiesIfNotPresent.yaml
new file mode 100644
index 00000000000..841cf77854e
--- /dev/null
+++ b/bin/configs/python-oas2_disallowAdditionalPropertiesIfNotPresent.yaml
@@ -0,0 +1,7 @@
+generatorName: python
+outputDir: samples/client/petstore/python_disallowAdditionalPropertiesIfNotPresent
+inputSpec: modules/openapi-generator/src/test/resources/2_0/python-client-experimental/petstore-with-fake-endpoints-models-for-testing.yaml
+templateDir: modules/openapi-generator/src/main/resources/python
+additionalProperties:
+ disallowAdditionalPropertiesIfNotPresent: "true"
+ packageName: petstore_api
diff --git a/bin/configs/swift5-default.yaml b/bin/configs/swift5-default.yaml
index ede36e7331c..fffd318be1a 100644
--- a/bin/configs/swift5-default.yaml
+++ b/bin/configs/swift5-default.yaml
@@ -1,6 +1,6 @@
generatorName: swift5
outputDir: samples/client/petstore/swift5/default
-inputSpec: modules/openapi-generator/src/test/resources/2_0/swift/petstore-with-fake-endpoints-models-for-testing.yaml
+inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml
templateDir: modules/openapi-generator/src/main/resources/swift5
generateAliasAsModel: true
additionalProperties:
diff --git a/bin/configs/swift5-rxswiftLibrary.yaml b/bin/configs/swift5-rxswiftLibrary.yaml
index f564ac3340c..49d0e24cca5 100644
--- a/bin/configs/swift5-rxswiftLibrary.yaml
+++ b/bin/configs/swift5-rxswiftLibrary.yaml
@@ -9,3 +9,4 @@ additionalProperties:
podSummary: PetstoreClient
projectName: PetstoreClient
podHomepage: https://github.com/openapitools/openapi-generator
+ useBacktickEscapes: true
diff --git a/bin/configs/swift5-urlsessionLibrary.yaml b/bin/configs/swift5-urlsessionLibrary.yaml
index 2fe5ecca0c7..b260611e602 100644
--- a/bin/configs/swift5-urlsessionLibrary.yaml
+++ b/bin/configs/swift5-urlsessionLibrary.yaml
@@ -9,3 +9,5 @@ additionalProperties:
podSummary: PetstoreClient
projectName: PetstoreClient
podHomepage: https://github.com/openapitools/openapi-generator
+ useSPMFileStructure: true
+ useClasses: true
diff --git a/bin/configs/typescript-axios-with-fake-endpoints-models-for-testing-with-http-signature.yaml b/bin/configs/typescript-axios-with-fake-endpoints-models-for-testing-with-http-signature.yaml
new file mode 100644
index 00000000000..1cb364d79ea
--- /dev/null
+++ b/bin/configs/typescript-axios-with-fake-endpoints-models-for-testing-with-http-signature.yaml
@@ -0,0 +1,3 @@
+generatorName: typescript-axios
+outputDir: samples/client/petstore/typescript-axios/builds/with-fake-endpoints-models-for-testing-with-http-signature
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml
diff --git a/bin/meta-codegen.sh b/bin/meta-codegen.sh
index d2a05a0fe6a..5b90f6abc8c 100755
--- a/bin/meta-codegen.sh
+++ b/bin/meta-codegen.sh
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
+set -e
+
SCRIPT="$0"
echo "# START SCRIPT: $SCRIPT"
@@ -18,8 +20,8 @@ ags="meta -n myClientCodegen -t DOCUMENTATION -p com.my.company.codegen -o sampl
java $JAVA_OPTS -jar $executable $ags
-(cd "$root"/samples/meta-codegen/ && mvn -B package -Djacoco.skip=true -DskipTests=true -f pom.xml)
+(./mvnw -B package -Djacoco.skip=true -DskipTests=true -f "$root"/samples/meta-codegen/pom.xml)
-ags2="generate -g myClientCodegen -i modules/openapi-generator/src/test/resources/2_0/petstore.json -o samples/meta-codegen/usage $@"
+ags2="generate -g myClientCodegen -i modules/openapi-generator/src/test/resources/3_0/petstore.json -o samples/meta-codegen/usage $@"
-java $JAVA_OPTS -cp ${root}/samples/meta-codegen/lib/target/myClientCodegen-openapi-generator-1.0.0.jar:$executable org.openapitools.codegen.OpenAPIGenerator $ags2
\ No newline at end of file
+java $JAVA_OPTS -cp ${root}/samples/meta-codegen/lib/target/myClientCodegen-openapi-generator-1.0.0.jar:$executable org.openapitools.codegen.OpenAPIGenerator $ags2
diff --git a/bin/utils/test-fake-petstore-for-all.sh b/bin/utils/test-fake-petstore-for-all.sh
index 6be320d6b99..1ec62890c3b 100755
--- a/bin/utils/test-fake-petstore-for-all.sh
+++ b/bin/utils/test-fake-petstore-for-all.sh
@@ -11,15 +11,16 @@ logfile="/tmp/generator-fake-petstore-output.log"
for GENERATOR in $(java -jar ${executable} list --short | sed -e 's/,/\'$'\n''/g')
do
- if eval java -jar ${executable} generate -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g ${GENERATOR} -o /tmp/openapi-generator-test-fake-petstore/2.0/${GENERATOR} > ${logfile} 2>&1; then
- echo "[OAS 2.0] Executed ${GENERATOR} successfully!"
- else
- echo "ERROR: Failed to run '${GENERATOR}' generator. The command was:"
- echo "java -jar ${executable} generate -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g ${GENERATOR} -o /tmp/openapi-generator-test-fake-petstore/2.0/${GENERATOR}"
- echo "ERROR: The output of the command was:"
- cat ${logfile}
- exit 1
- fi
+ # no longer test 2.0 spec as we migrated to 3.0 spec
+ #if eval java -jar ${executable} generate -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g ${GENERATOR} -o /tmp/openapi-generator-test-fake-petstore/2.0/${GENERATOR} > ${logfile} 2>&1; then
+ # echo "[OAS 2.0] Executed ${GENERATOR} successfully!"
+ #else
+ # echo "ERROR: Failed to run '${GENERATOR}' generator. The command was:"
+ # echo "java -jar ${executable} generate -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g ${GENERATOR} -o /tmp/openapi-generator-test-fake-petstore/2.0/${GENERATOR}"
+ # echo "ERROR: The output of the command was:"
+ # cat ${logfile}
+ # exit 1
+ #fi
if eval java -jar ${executable} generate -i modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml -g ${GENERATOR} -o /tmp/openapi-generator-test-fake-petstore/3.0/${GENERATOR} > ${logfile} 2>&1; then
echo "[OAS 3.0] Executed ${GENERATOR} successfully!"
diff --git a/bin/utils/test_file_list.yaml b/bin/utils/test_file_list.yaml
index 9d55e425058..286c876104e 100644
--- a/bin/utils/test_file_list.yaml
+++ b/bin/utils/test_file_list.yaml
@@ -1,7 +1,7 @@
---
# csharp-netcore test files and image for upload
- filename: "samples/client/petstore/csharp-netcore/OpenAPIClient/src/Org.OpenAPITools.Test/JSONComposedSchemaTests.cs"
- sha256: ec34838fbbb1abb9f762949d510503b6237b607400a85c848c234c39d013a776
+ sha256: 95e40cace36e7cd1608fa494161f06291f4cfb8f859ec4196ae9939f520b152a
- filename: "samples/client/petstore/csharp-netcore/OpenAPIClient/src/Org.OpenAPITools.Test/Api/PetApiTests.cs"
sha256: dae985015ba461297927d544a78267f2def35e07c3f14ca66468fd61e1fd1c26
- filename: "samples/client/petstore/csharp-netcore/OpenAPIClient/src/Org.OpenAPITools.Test/linux-logo.png"
diff --git a/docs/file-post-processing.md b/docs/file-post-processing.md
index b0c66e28f8d..a23845adae2 100644
--- a/docs/file-post-processing.md
+++ b/docs/file-post-processing.md
@@ -22,7 +22,6 @@ The following environment variables are supported by their respective generators
* `CPP_POST_PROCESS_FILE`
* `CSHARP_POST_PROCESS_FILE`
* `C_POST_PROCESS_FILE`
-* `DART_POST_PROCESS`
* `DART_POST_PROCESS_FILE`
* `FSHARP_POST_PROCESS_FILE`
* `GO_POST_PROCESS_FILE`
diff --git a/docs/generators.md b/docs/generators.md
index e581cc54fb1..521bdc3dbf0 100644
--- a/docs/generators.md
+++ b/docs/generators.md
@@ -86,6 +86,7 @@ The following generators are available:
* [erlang-server](generators/erlang-server.md)
* [fsharp-functions (beta)](generators/fsharp-functions.md)
* [fsharp-giraffe-server (beta)](generators/fsharp-giraffe-server.md)
+* [go-echo-server (beta)](generators/go-echo-server.md)
* [go-gin-server](generators/go-gin-server.md)
* [go-server](generators/go-server.md)
* [graphql-nodejs-express-server](generators/graphql-nodejs-express-server.md)
diff --git a/docs/generators/csharp-netcore.md b/docs/generators/csharp-netcore.md
index c7935752d01..0887dcbfeca 100644
--- a/docs/generators/csharp-netcore.md
+++ b/docs/generators/csharp-netcore.md
@@ -29,7 +29,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|returnICollection|Return ICollection<T> instead of the concrete type.| |false|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|sourceFolder|source folder for generated code| |src|
-|targetFramework|The target .NET framework version.|
**netstandard1.3** .NET Standard 1.3 compatible **netstandard1.4** .NET Standard 1.4 compatible **netstandard1.5** .NET Standard 1.5 compatible **netstandard1.6** .NET Standard 1.6 compatible **netstandard2.0** .NET Standard 2.0 compatible **netstandard2.1** .NET Standard 2.1 compatible **netcoreapp2.0** .NET Core 2.0 compatible **netcoreapp2.1** .NET Core 2.1 compatible **netcoreapp3.0** .NET Core 3.0 compatible **netcoreapp3.1** .NET Core 3.1 compatible **net47** .NET Framework 4.7 compatible **net5.0** .NET 5.0 compatible |netstandard2.0|
+|targetFramework|The target .NET framework version. To target multiple frameworks, use `;` as the separator, e.g. `netstandard2.1;netcoreapp3.0`|**netstandard1.3** .NET Standard 1.3 compatible **netstandard1.4** .NET Standard 1.4 compatible **netstandard1.5** .NET Standard 1.5 compatible **netstandard1.6** .NET Standard 1.6 compatible **netstandard2.0** .NET Standard 2.0 compatible **netstandard2.1** .NET Standard 2.1 compatible **netcoreapp2.0** .NET Core 2.0 compatible **netcoreapp2.1** .NET Core 2.1 compatible **netcoreapp3.0** .NET Core 3.0 compatible **netcoreapp3.1** .NET Core 3.1 compatible **net47** .NET Framework 4.7 compatible **net5.0** .NET 5.0 compatible |netstandard2.0|
|useCollection|Deserialize array types to Collection<T> instead of List<T>.| |false|
|useDateTimeOffset|Use DateTimeOffset to model date-time properties| |false|
|useOneOfDiscriminatorLookup|Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and only one match in oneOf's schemas) will be skipped.| |false|
diff --git a/docs/generators/csharp.md b/docs/generators/csharp.md
index ec9c4454ff8..0b3185606ec 100644
--- a/docs/generators/csharp.md
+++ b/docs/generators/csharp.md
@@ -25,7 +25,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|returnICollection|Return ICollection<T> instead of the concrete type.| |false|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|sourceFolder|source folder for generated code| |src|
-|targetFramework|The target .NET framework version.|**v3.5** .NET Framework 3.5 compatible **v4.0** .NET Framework 4.0 compatible **v4.5** .NET Framework 4.5 compatible **v4.5.2** .NET Framework 4.5.2+ compatible **netstandard1.3** .NET Standard 1.3 compatible (DEPRECATED. Please use `csharp-netcore` generator instead) **uwp** Universal Windows Platform (DEPRECATED. Please use `csharp-netcore` generator instead) |v4.5|
+|targetFramework|The target .NET framework version. To target multiple frameworks, use `;` as the separator, e.g. `netstandard2.1;netcoreapp3.0`|**v3.5** .NET Framework 3.5 compatible **v4.0** .NET Framework 4.0 compatible **v4.5** .NET Framework 4.5 compatible **v4.5.2** .NET Framework 4.5.2+ compatible **netstandard1.3** .NET Standard 1.3 compatible (DEPRECATED. Please use `csharp-netcore` generator instead) **uwp** Universal Windows Platform (DEPRECATED. Please use `csharp-netcore` generator instead) |v4.5|
|useCollection|Deserialize array types to Collection<T> instead of List<T>.| |false|
|useCompareNetObjects|Use KellermanSoftware.CompareNetObjects for deep recursive object comparison. WARNING: this option incurs potential performance impact.| |false|
|useDateTimeOffset|Use DateTimeOffset to model date-time properties| |false|
diff --git a/docs/generators/dart-dio-next.md b/docs/generators/dart-dio-next.md
index da4fbe4f9a8..d644e35b04a 100644
--- a/docs/generators/dart-dio-next.md
+++ b/docs/generators/dart-dio-next.md
@@ -44,7 +44,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
String
bool
double
-dynamic
int
num
diff --git a/docs/generators/dart-dio.md b/docs/generators/dart-dio.md
index 767884d7eeb..9368dc7e7fc 100644
--- a/docs/generators/dart-dio.md
+++ b/docs/generators/dart-dio.md
@@ -30,11 +30,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Type/Alias | Imports |
| ---------- | ------- |
-|BuiltList|package:built_collection/built_collection.dart|
-|BuiltMap|package:built_collection/built_collection.dart|
-|BuiltSet|package:built_collection/built_collection.dart|
-|JsonObject|package:built_value/json_object.dart|
-|Uint8List|dart:typed_data|
## INSTANTIATION TYPES
@@ -49,7 +44,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
String
bool
double
-dynamic
int
num
diff --git a/docs/generators/dart-jaguar.md b/docs/generators/dart-jaguar.md
index d357bae3146..068b5728f02 100644
--- a/docs/generators/dart-jaguar.md
+++ b/docs/generators/dart-jaguar.md
@@ -44,7 +44,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
String
bool
double
-dynamic
int
num
diff --git a/docs/generators/dart.md b/docs/generators/dart.md
index d550256877c..ef805b78451 100644
--- a/docs/generators/dart.md
+++ b/docs/generators/dart.md
@@ -43,7 +43,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
String
bool
double
-dynamic
int
num
diff --git a/docs/generators/go-echo-server.md b/docs/generators/go-echo-server.md
new file mode 100644
index 00000000000..53c726fb85e
--- /dev/null
+++ b/docs/generators/go-echo-server.md
@@ -0,0 +1,206 @@
+---
+title: Config Options for go-echo-server
+sidebar_label: go-echo-server
+---
+
+These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details.
+
+| Option | Description | Values | Default |
+| ------ | ----------- | ------ | ------- |
+|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true|
+|packageName|Go package name (convention: lowercase).| |openapi|
+|packageVersion|Go package version.| |1.0.0|
+|serverPort|The network port the generated server binds to| |8080|
+
+## IMPORT MAPPING
+
+| Type/Alias | Imports |
+| ---------- | ------- |
+
+
+## INSTANTIATION TYPES
+
+| Type/Alias | Instantiated By |
+| ---------- | --------------- |
+
+
+## LANGUAGE PRIMITIVES
+
+
+bool
+byte
+complex128
+complex64
+float32
+float64
+int
+int32
+int64
+interface{}
+map[string]interface{}
+rune
+string
+uint
+uint32
+uint64
+
+
+## RESERVED WORDS
+
+
+bool
+break
+byte
+case
+chan
+complex128
+complex64
+const
+continue
+default
+defer
+else
+error
+fallthrough
+float32
+float64
+for
+func
+go
+goto
+if
+import
+int
+int16
+int32
+int64
+int8
+interface
+map
+nil
+package
+range
+return
+rune
+select
+string
+struct
+switch
+type
+uint
+uint16
+uint32
+uint64
+uint8
+uintptr
+var
+
+
+## FEATURE SET
+
+
+### Client Modification Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|BasePath|✗|ToolingExtension
+|Authorizations|✗|ToolingExtension
+|UserAgent|✗|ToolingExtension
+|MockServer|✗|ToolingExtension
+
+### Data Type Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Custom|✗|OAS2,OAS3
+|Int32|✓|OAS2,OAS3
+|Int64|✓|OAS2,OAS3
+|Float|✓|OAS2,OAS3
+|Double|✓|OAS2,OAS3
+|Decimal|✓|ToolingExtension
+|String|✓|OAS2,OAS3
+|Byte|✓|OAS2,OAS3
+|Binary|✓|OAS2,OAS3
+|Boolean|✓|OAS2,OAS3
+|Date|✓|OAS2,OAS3
+|DateTime|✓|OAS2,OAS3
+|Password|✓|OAS2,OAS3
+|File|✓|OAS2
+|Array|✓|OAS2,OAS3
+|Maps|✓|ToolingExtension
+|CollectionFormat|✓|OAS2
+|CollectionFormatMulti|✓|OAS2
+|Enum|✓|OAS2,OAS3
+|ArrayOfEnum|✓|ToolingExtension
+|ArrayOfModel|✓|ToolingExtension
+|ArrayOfCollectionOfPrimitives|✓|ToolingExtension
+|ArrayOfCollectionOfModel|✓|ToolingExtension
+|ArrayOfCollectionOfEnum|✓|ToolingExtension
+|MapOfEnum|✓|ToolingExtension
+|MapOfModel|✓|ToolingExtension
+|MapOfCollectionOfPrimitives|✓|ToolingExtension
+|MapOfCollectionOfModel|✓|ToolingExtension
+|MapOfCollectionOfEnum|✓|ToolingExtension
+
+### Documentation Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Readme|✓|ToolingExtension
+|Model|✓|ToolingExtension
+|Api|✓|ToolingExtension
+
+### Global Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Host|✓|OAS2,OAS3
+|BasePath|✓|OAS2,OAS3
+|Info|✓|OAS2,OAS3
+|Schemes|✗|OAS2,OAS3
+|PartialSchemes|✓|OAS2,OAS3
+|Consumes|✓|OAS2
+|Produces|✓|OAS2
+|ExternalDocumentation|✓|OAS2,OAS3
+|Examples|✓|OAS2,OAS3
+|XMLStructureDefinitions|✗|OAS2,OAS3
+|MultiServer|✗|OAS3
+|ParameterizedServer|✗|OAS3
+|ParameterStyling|✗|OAS3
+|Callbacks|✗|OAS3
+|LinkObjects|✗|OAS3
+
+### Parameter Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Path|✓|OAS2,OAS3
+|Query|✓|OAS2,OAS3
+|Header|✓|OAS2,OAS3
+|Body|✓|OAS2
+|FormUnencoded|✓|OAS2
+|FormMultipart|✓|OAS2
+|Cookie|✗|OAS3
+
+### Schema Support Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Simple|✓|OAS2,OAS3
+|Composite|✓|OAS2,OAS3
+|Polymorphism|✗|OAS2,OAS3
+|Union|✗|OAS3
+
+### Security Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|BasicAuth|✗|OAS2,OAS3
+|ApiKey|✗|OAS2,OAS3
+|OpenIDConnect|✗|OAS3
+|BearerToken|✗|OAS3
+|OAuth2_Implicit|✗|OAS2,OAS3
+|OAuth2_Password|✗|OAS2,OAS3
+|OAuth2_ClientCredentials|✗|OAS2,OAS3
+|OAuth2_AuthorizationCode|✗|OAS2,OAS3
+
+### Wire Format Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|JSON|✓|OAS2,OAS3
+|XML|✓|OAS2,OAS3
+|PROTOBUF|✗|ToolingExtension
+|Custom|✗|OAS2,OAS3
diff --git a/docs/generators/go-server.md b/docs/generators/go-server.md
index e0abd3de52c..36ac78aea6d 100644
--- a/docs/generators/go-server.md
+++ b/docs/generators/go-server.md
@@ -7,6 +7,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
+|addResponseHeaders|To include response headers in ImplResponse| |false|
|enumClassPrefix|Prefix enum with class name| |false|
|featureCORS|Enable Cross-Origin Resource Sharing middleware| |false|
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true|
diff --git a/docs/generators/python.md b/docs/generators/python.md
index 4cf503ff278..fe60f0e511c 100644
--- a/docs/generators/python.md
+++ b/docs/generators/python.md
@@ -7,6 +7,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
+|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|**false** The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications. **true** Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default. NOTE: this option breaks composition and will be removed in 6.0.0 |false|
|generateSourceCodeOnly|Specifies that only a library source code is to be generated.| |false|
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true|
|library|library template (sub-template) to use: asyncio, tornado, urllib3| |urllib3|
@@ -28,7 +29,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Type/Alias | Instantiated By |
| ---------- | --------------- |
-|map|dict|
## LANGUAGE PRIMITIVES
diff --git a/docs/generators/swift5.md b/docs/generators/swift5.md
index ebf6f2b0e86..9774b434f13 100644
--- a/docs/generators/swift5.md
+++ b/docs/generators/swift5.md
@@ -33,7 +33,10 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|responseAs|Optionally use libraries to manage response. Currently PromiseKit, RxSwift, Result, Combine are available.| |null|
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
+|swiftPackagePath|Set a custom source path instead of OpenAPIClient/Classes/OpenAPIs.| |null|
|swiftUseApiNamespace|Flag to make all the API classes inner-class of {{projectName}}API| |null|
+|useBacktickEscapes|Escape reserved words using backticks (default: false)| |false|
+|useSPMFileStructure|Use SPM file structure and set the source path to Sources/{{projectName}} (default: false).| |null|
## IMPORT MAPPING
diff --git a/docs/plugins.md b/docs/plugins.md
index 224a0d5fa58..691c5fa85d1 100644
--- a/docs/plugins.md
+++ b/docs/plugins.md
@@ -15,7 +15,9 @@ Add to your `build->plugins` section (default phase is `generate-sources` phase)
org.openapitools
openapi-generator-maven-plugin
- 5.0.0
+
+ 5.1.0
+
diff --git a/docs/templating.md b/docs/templating.md
index fa901bc65aa..aba3fd49274 100644
--- a/docs/templating.md
+++ b/docs/templating.md
@@ -910,9 +910,9 @@ x-content-type: application/json
### Rust-server
-#### x-responseId
+#### x-response-id
-Each response may specify a unique `x-responseId`. `rust-server` will use this to name the corresponding enum variant in the code. e.g.
+Each response may specify a unique `x-response-id`. `rust-server` will use this to name the corresponding enum variant in the code. e.g.
```yaml
paths:
@@ -921,7 +921,7 @@ paths:
responses:
200:
description: OK
- x-responseId: Pong
+ x-response-id: Pong
```
### MySQL Schema
diff --git a/docs/usage.md b/docs/usage.md
index a5719e27761..bad47c90ade 100644
--- a/docs/usage.md
+++ b/docs/usage.md
@@ -10,12 +10,13 @@ This page demonstrates navigating the options via CLI. Commands are presented he
The `help` option lists all commands available to the CLI.
-```bash
+```text
openapi-generator-cli help
usage: openapi-generator-cli []
The most commonly used openapi-generator-cli commands are:
author Utilities for authoring generators or customizing templates.
+ batch Generate code in batch via external configs.
config-help Config help for chosen lang
generate Generate code with the specified generator.
help Display help information about openapi-generator
@@ -30,26 +31,28 @@ command.
## version
-The version command provides version information, returning either the semver version by default or the git sha when passed `--sha`.
+The version command provides version information, returning either the version by default, the git commit sha when passed `--sha`, or verbose output when passed `--full`.
-```bash
+```text
NAME
- openapi-generator-cli version - Show version information
+ openapi-generator-cli version - Show version information used in tooling
SYNOPSIS
- openapi-generator-cli version [--sha]
+ openapi-generator-cli version [--full] [--sha]
OPTIONS
+ --full
+ Full version details
+
--sha
Git commit SHA version
-
```
## list
The `list` command outputs a formatted list of every available generator. Pass the `-s/--short` option if you would like a CSV output for easy parsing.
-```bash
+```text
openapi-generator-cli help list
NAME
openapi-generator-cli list - Lists the available generators
@@ -66,7 +69,6 @@ OPTIONS
-s, --short
shortened output (suitable for scripting)
-
```
Example:
@@ -81,26 +83,49 @@ For the full list of generators, refer to the [Generators List](./generators.md)
The `config-help` option provides details about
-```bash
+```text
openapi-generator-cli help config-help
NAME
openapi-generator-cli config-help - Config help for chosen lang
SYNOPSIS
openapi-generator-cli config-help
- [(-f | --format )]
+ [(-f | --format )] [--feature-set]
+ [--full-details]
[(-g | --generator-name )]
- [--markdown-header] [--named-header]
- [(-o | --output )]
+ [--import-mappings] [--instantiation-types]
+ [--language-specific-primitive] [--markdown-header] [--named-header]
+ [(-o | --output )] [--reserved-words]
OPTIONS
-f , --format
Write output files in the desired format. Options are 'text',
'markdown' or 'yamlsample'. Default is 'text'.
+ --feature-set
+ displays feature set as supported by the generator
+
+ --full-details
+ displays CLI options as well as other configs/mappings (implies
+ --instantiation-types, --reserved-words,
+ --language-specific-primitives, --import-mappings,
+ --supporting-files)
+
-g , --generator-name
generator to get config help for
+ --import-mappings
+ displays the default import mappings (types and aliases, and what
+ imports they will pull into the template)
+
+ --instantiation-types
+ displays types used to instantiate simple type/alias names
+
+ --language-specific-primitive
+ displays the language specific primitives (types which require no
+ additional imports, or which may conflict with user defined model
+ names)
+
--markdown-header
When format=markdown, include this option to write out markdown
headers (e.g. for docusaurus).
@@ -112,6 +137,9 @@ OPTIONS
Optionally write help to this location, otherwise default is
standard output
+ --reserved-words
+ displays the reserved words which may result in renamed model or
+ property names
```
The option of note is `-g/--generator-name` (other options are exposed for tooling).
@@ -153,7 +181,7 @@ To pass these go client generator-specific options to the `generate` command for
The `meta` command creates a new Java class and template files, used for creating your own custom templates.
-```bash
+```text
openapi-generator-cli help meta
NAME
openapi-generator-cli meta - MetaGenerator. Generator for creating a new
@@ -161,11 +189,15 @@ NAME
the language you specify, and includes default templates to include.
SYNOPSIS
- openapi-generator-cli meta [(-n | --name )]
+ openapi-generator-cli meta [(-l | --language )]
+ [(-n | --name )]
[(-o | --output )]
[(-p | --package )] [(-t | --type )]
OPTIONS
+ -l , --language
+ the implementation language for the generator class
+
-n , --name
the human-readable name of the generator
@@ -186,7 +218,7 @@ For an in-depth example of using the `meta` command, see [Customization](./custo
The `validate` command allows you to validate an input specification, optionally providing recommendations for error fixes or other improvements (if available).
-```bash
+```text
openapi-generator-cli help validate
NAME
openapi-generator-cli validate - Validate specification
@@ -200,7 +232,6 @@ OPTIONS
location of the OpenAPI spec, as URL or file (required)
--recommend
-
```
Valid Spec Example (using [petstore-v3.0.yaml](https://raw.githubusercontent.com/OpenAPITools/openapi-generator/master/modules/openapi-generator-gradle-plugin/samples/local-spec/petstore-v3.0.yaml))
@@ -250,7 +281,7 @@ An example bash completion script can be found in the repo at [scripts/openapi-g
The `generate` command is the workhorse of the generator toolset. As such, it has _many_ more options available than the previous commands. The abbreviated options are below, but you may expand the full descriptions.
-```bash
+```text
openapi-generator-cli help generate
NAME
openapi-generator-cli generate - Generate code with the specified
@@ -269,23 +300,24 @@ SYNOPSIS
[--git-repo-id ] [--git-user-id ]
[--global-property ...] [--group-id ]
[--http-user-agent ]
- (-i | --input-spec )
+ [(-i | --input-spec )]
[--ignore-file-override ]
[--import-mappings ...]
[--instantiation-types ...]
[--invoker-package ]
[--language-specific-primitives ...]
- [--library ] [--log-to-stderr] [--minimal-update]
+ [--legacy-discriminator-behavior] [--library ]
+ [--log-to-stderr] [--minimal-update]
[--model-name-prefix ]
[--model-name-suffix ]
[--model-package ]
- [(-o | --output )]
- [(-p | --additional-properties )...]
+ [(-o | --output )] [(-p | --additional-properties )...]
[--package-name ] [--release-note ]
[--remove-operation-id-prefix]
[--reserved-words-mappings ...]
[(-s | --skip-overwrite)] [--server-variables ...]
- [--skip-validate-spec] [--strict-spec ]
+ [--skip-operation-example] [--skip-validate-spec]
+ [--strict-spec ]
[(-t | --template-dir )]
[--type-mappings ...] [(-v | --verbose)]
```
@@ -293,7 +325,7 @@ SYNOPSIS
generate OPTIONS
-```bash
+```text
OPTIONS
-a , --auth
adds authorization headers when fetching the OpenAPI definitions
@@ -303,7 +335,7 @@ OPTIONS
--api-name-suffix
Suffix that will be appended to all API names ('tags'). Default:
Api. e.g. Pet => PetApi. Note: Only ruby, python, jaxrs generators
- suppport this feature at the moment.
+ support this feature at the moment.
--api-package
package for generated api classes
@@ -367,7 +399,8 @@ OPTIONS
'OpenAPI-Generator/{packageVersion}/{language}'
-i , --input-spec
- location of the OpenAPI spec, as URL or file (required)
+ location of the OpenAPI spec, as URL or file (required if not loaded
+ via config using -c)
--ignore-file-override
Specifies an override location for the .openapi-generator-ignore
@@ -394,13 +427,18 @@ OPTIONS
String,boolean,Boolean,Double. You can also have multiple
occurrences of this option.
+ --legacy-discriminator-behavior
+ Set to false for generators with better support for discriminators.
+ (Python, Java, Go, PowerShell, C#have this enabled by default).
+
--library
library template (sub-template)
--log-to-stderr
write all log messages (not just errors) to STDOUT. Useful for
- piping the JSON output of debug options (e.g. `--global-property debugOperations=true`)
- to an external parser directly while testing a generator.
+ piping the JSON output of debug options (e.g. `--global-property
+ debugOperations`) to an external parser directly while testing a
+ generator.
--minimal-update
Only write output files that have changed.
@@ -445,6 +483,9 @@ OPTIONS
sets server variables overrides for spec documents which support
variable templating of servers.
+ --skip-operation-example
+ Skip examples defined in operations to avoid out of memory errors.
+
--skip-validate-spec
Skips the default behavior of validating an input specification.
@@ -464,7 +505,6 @@ OPTIONS
-v, --verbose
verbose mode
-
```
@@ -604,19 +644,22 @@ The `batch` command allows you to move all CLI arguments supported by the `gener
*NOTE*: This command supports an additional `!include` property which may point to another "shared" file, the base path to which can be
modified by `--includes-base-dir`. Starting with 5.0.0, the `!batch` command supports multiple `!include` properties, either sequential or nested. In order to support multiple `!include` properties in a JSON file, the property name can have a suffix, e.g. `!include1`, `!include2`, etc. The suffix have no meaning other than providing unique property names.
-```bash
+```text
openapi-generator-cli help batch
NAME
openapi-generator-cli batch - Generate code in batch via external
configs.
SYNOPSIS
- openapi-generator-cli batch [--fail-fast]
+ openapi-generator-cli batch [--clean] [--fail-fast]
[--includes-base-dir ] [(-r | --threads )]
[--root-dir ] [--timeout ] [(-v | --verbose)] [--]
...
OPTIONS
+ --clean
+ clean output of previously written files before generation
+
--fail-fast
fail fast on any errors
@@ -682,7 +725,7 @@ openapi-generator-cli batch *.yaml
This command group contains utilities for authoring generators or customizing templates.
-```
+```text
openapi-generator-cli help author
NAME
openapi-generator-cli author - Utilities for authoring generators or
@@ -690,9 +733,9 @@ NAME
SYNOPSIS
openapi-generator-cli author
- openapi-generator-cli author template [(-v | --verbose)]
+ openapi-generator-cli author template [--library ]
+ [(-v | --verbose)]
[(-o | --output )]
- [--library ]
(-g | --generator-name )
OPTIONS
@@ -708,13 +751,13 @@ COMMANDS
template
Retrieve templates for local modification
+ With --library option, library template (sub-template)
+
With --verbose option, verbose mode
With --output option, where to write the template files (defaults to
'out')
- With --library option, library template (sub-template)
-
With --generator-name option, generator to use (see list command for
list)
```
@@ -723,7 +766,8 @@ COMMANDS
This command allows user to extract templates from the CLI jar which simplifies customization efforts.
-```
+```text
+openapi-generator-cli help author template
NAME
openapi-generator-cli author template - Retrieve templates for local
modification
@@ -753,12 +797,12 @@ Example:
Extract Java templates, limiting to the `webclient` library.
-```
+```bash
openapi-generator-cli author template -g java --library webclient
```
Extract all Java templates:
-```
+```bash
openapi-generator-cli author template -g java
```
diff --git a/modules/openapi-generator-cli/Dockerfile b/modules/openapi-generator-cli/Dockerfile
index e9c64a54619..00fad3e7cdd 100644
--- a/modules/openapi-generator-cli/Dockerfile
+++ b/modules/openapi-generator-cli/Dockerfile
@@ -1,6 +1,4 @@
-FROM java:8-jre-alpine
-
-RUN apk add --no-cache bash
+FROM openjdk:11.0-jre-buster
ADD target/openapi-generator-cli.jar /opt/openapi-generator/modules/openapi-generator-cli/target/openapi-generator-cli.jar
diff --git a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java
index f935b14e6d7..27447fad78a 100644
--- a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java
+++ b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java
@@ -134,7 +134,8 @@ public class Generate extends OpenApiGeneratorCommand {
title = "type mappings",
description = "sets mappings between OpenAPI spec types and generated code types "
+ "in the format of OpenAPIType=generatedType,OpenAPIType=generatedType. For example: array=List,map=Map,string=String."
- + " You can also have multiple occurrences of this option.")
+ + " You can also have multiple occurrences of this option."
+ + " To map a specified format, use type+format, e.g. string+password=EncryptedString will map `type: string, format: password` to `EncryptedString`.")
private List typeMappings = new ArrayList<>();
@Option(
diff --git a/modules/openapi-generator-gradle-plugin/README.adoc b/modules/openapi-generator-gradle-plugin/README.adoc
index ae55fb16136..08b09304900 100644
--- a/modules/openapi-generator-gradle-plugin/README.adoc
+++ b/modules/openapi-generator-gradle-plugin/README.adoc
@@ -212,7 +212,7 @@ apply plugin: 'org.openapi.generator'
|typeMappings
|Map(String,String)
|None
-|Sets mappings between OpenAPI spec types and generated code types.
+|Sets mappings between OpenAPI spec types and generated code types in the format of OpenAPIType=generatedType,OpenAPIType=generatedType. For example: `array=List,map=Map,string=String`. You can also have multiple occurrences of this option. To map a specified format, use type+format, e.g. string+password=EncryptedString will map `type: string, format: password` to `EncryptedString`.
|additionalProperties
|Map(String,Any)
diff --git a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt
index b1dcd474ae8..c3e1efcee94 100644
--- a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt
+++ b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt
@@ -81,9 +81,8 @@ open class GenerateTask : DefaultTask() {
val outputDir = project.objects.property()
@Suppress("unused")
- @get:Internal
@set:Option(option = "input", description = "The input specification.")
- @Input
+ @Internal
var input: String? = null
set(value) {
inputSpec.set(value)
diff --git a/modules/openapi-generator-maven-plugin/README.md b/modules/openapi-generator-maven-plugin/README.md
index 627fa155e63..64151ad1418 100644
--- a/modules/openapi-generator-maven-plugin/README.md
+++ b/modules/openapi-generator-maven-plugin/README.md
@@ -79,7 +79,7 @@ mvn clean compile
| `configOptions` | N/A | a **map** of language-specific parameters. To show a full list of generator-specified parameters (options), please use `configHelp` (explained below)
| `instantiationTypes` | `openapi.generator.maven.plugin.instantiationTypes` | sets instantiation type mappings in the format of type=instantiatedType,type=instantiatedType. For example (in Java): `array=ArrayList,map=HashMap`. In other words array types will get instantiated as ArrayList in generated code. You can also have multiple occurrences of this option
| `importMappings` | `openapi.generator.maven.plugin.importMappings` | specifies mappings between a given class and the import that should be used for that class in the format of type=import,type=import. You can also have multiple occurrences of this option
-| `typeMappings` | `openapi.generator.maven.plugin.typeMappings` | sets mappings between OpenAPI spec types and generated code types in the format of OpenAPIType=generatedType,OpenAPIType=generatedType. For example: `array=List,map=Map,string=String`. You can also have multiple occurrences of this option
+| `typeMappings` | `openapi.generator.maven.plugin.typeMappings` | sets mappings between OpenAPI spec types and generated code types in the format of OpenAPIType=generatedType,OpenAPIType=generatedType. For example: `array=List,map=Map,string=String`. You can also have multiple occurrences of this option. To map a specified format, use type+format, e.g. string+password=EncryptedString will map `type: string, format: password` to `EncryptedString`.
| `languageSpecificPrimitives` | `openapi.generator.maven.plugin.languageSpecificPrimitives` | specifies additional language specific primitive types in the format of type1,type2,type3,type3. For example: `String,boolean,Boolean,Double`. You can also have multiple occurrences of this option
| `additionalProperties` | `openapi.generator.maven.plugin.additionalProperties` | sets additional properties that can be referenced by the mustache templates in the format of name=value,name=value. You can also have multiple occurrences of this option
| `serverVariableOverrides` | `openapi.generator.maven.plugin.serverVariableOverrides` | A map of server variable overrides for specs that support server URL templating
diff --git a/modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/CodeGenMojo.java b/modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/CodeGenMojo.java
index a697be42e32..8949156f4d8 100644
--- a/modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/CodeGenMojo.java
+++ b/modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/CodeGenMojo.java
@@ -43,6 +43,7 @@ import com.google.common.io.CharSource;
import io.swagger.v3.parser.util.ClasspathHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
@@ -423,6 +424,9 @@ public class CodeGenMojo extends AbstractMojo {
@Parameter(property = "codegen.configHelp")
private boolean configHelp = false;
+ @Parameter(defaultValue = "${mojoExecution}", readonly = true)
+ private MojoExecution mojo;
+
/**
* The project being built.
*/
@@ -847,7 +851,7 @@ public class CodeGenMojo extends AbstractMojo {
name = Files.getNameWithoutExtension(segments[segments.length - 1]);
}
- return new File(output.getPath() + File.separator + ".openapi-generator" + File.separator + name + ".sha256");
+ return new File(output.getPath() + File.separator + ".openapi-generator" + File.separator + name + "-" + mojo.getExecutionId() + ".sha256");
}
private String getCompileSourceRoot() {
diff --git a/modules/openapi-generator-maven-plugin/src/test/java/org/openapitools/codegen/plugin/CodeGenMojoTest.java b/modules/openapi-generator-maven-plugin/src/test/java/org/openapitools/codegen/plugin/CodeGenMojoTest.java
index 521cb8e5efb..ad69be7e720 100644
--- a/modules/openapi-generator-maven-plugin/src/test/java/org/openapitools/codegen/plugin/CodeGenMojoTest.java
+++ b/modules/openapi-generator-maven-plugin/src/test/java/org/openapitools/codegen/plugin/CodeGenMojoTest.java
@@ -16,9 +16,20 @@
package org.openapitools.codegen.plugin;
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.execution.DefaultMavenExecutionRequest;
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.MojoExecution;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.ProjectBuilder;
+import org.apache.maven.project.ProjectBuildingRequest;
+import org.eclipse.aether.DefaultRepositorySystemSession;
import org.openapitools.codegen.plugin.stubs.StubUtility;
import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Map;
public class CodeGenMojoTest extends BaseTestCase {
@@ -29,8 +40,8 @@ public class CodeGenMojoTest extends BaseTestCase {
@SuppressWarnings("unchecked")
public void testCommonConfiguration() throws Exception {
- File testPom = StubUtility.basedPath(getUnitTestDir().toFile(), "common-maven", "common-maven.xml").toFile();
- final CodeGenMojo mojo = (CodeGenMojo) lookupMojo("generate", testPom);
+ File folder = Files.createTempDirectory("test").toFile();
+ CodeGenMojo mojo = loadMojo(folder, "src/test/resources/default");
mojo.execute();
assertEquals("java", getVariableValueFromObject(mojo, "generatorName"));
assertEquals("jersey2", getVariableValueFromObject(mojo, "library"));
@@ -42,4 +53,49 @@ public class CodeGenMojoTest extends BaseTestCase {
assertNotNull(configOptions);
assertEquals("joda", configOptions.get("dateLibrary"));
}
+
+ public void testHashGenerationFileContainsExecutionId() throws Exception {
+ // GIVEN
+ Path folder = Files.createTempDirectory("test");
+ CodeGenMojo mojo = loadMojo(folder.toFile(), "src/test/resources/default", "executionId");
+
+ // WHEN
+ mojo.execute();
+
+ // THEN
+ Path hashFolder = folder.resolve("target/generated-sources/common-maven/remote-openapi/.openapi-generator");
+ assertTrue(hashFolder.resolve("petstore.yaml-executionId.sha256").toFile().exists());
+ }
+
+ protected CodeGenMojo loadMojo(File temporaryFolder, String projectRoot) throws Exception {
+ return loadMojo(temporaryFolder, projectRoot, "default");
+ }
+
+ protected CodeGenMojo loadMojo(File temporaryFolder, String projectRoot, String executionId) throws Exception {
+ File file = new File(projectRoot);
+ FileUtils.copyDirectory(file, temporaryFolder);
+ MavenProject project = readMavenProject(temporaryFolder);
+ MavenSession session = newMavenSession(project);
+ MojoExecution execution = newMojoExecution("generate");
+ MojoExecution executionWithId = copyWithExecutionId(executionId, execution);
+ return (CodeGenMojo) lookupConfiguredMojo(session, executionWithId);
+ }
+
+ private MojoExecution copyWithExecutionId(String executionId, MojoExecution execution) {
+ MojoExecution executionWithId = new MojoExecution(execution.getMojoDescriptor(), executionId);
+ executionWithId.setConfiguration(execution.getConfiguration());
+ return executionWithId;
+ }
+
+ protected MavenProject readMavenProject(File basedir)
+ throws Exception {
+ File pom = new File(basedir, "pom.xml");
+ MavenExecutionRequest request = new DefaultMavenExecutionRequest();
+ request.setBaseDirectory(basedir);
+ ProjectBuildingRequest configuration = request.getProjectBuildingRequest();
+ configuration.setRepositorySession(new DefaultRepositorySystemSession());
+ MavenProject project = lookup(ProjectBuilder.class).build(pom, configuration).getProject();
+ assertNotNull(project);
+ return project;
+ }
}
\ No newline at end of file
diff --git a/modules/openapi-generator-maven-plugin/src/test/resources/unit/common-maven/petstore.yaml b/modules/openapi-generator-maven-plugin/src/test/resources/default/petstore.yaml
similarity index 100%
rename from modules/openapi-generator-maven-plugin/src/test/resources/unit/common-maven/petstore.yaml
rename to modules/openapi-generator-maven-plugin/src/test/resources/default/petstore.yaml
diff --git a/modules/openapi-generator-maven-plugin/src/test/resources/unit/common-maven/common-maven.xml b/modules/openapi-generator-maven-plugin/src/test/resources/default/pom.xml
similarity index 89%
rename from modules/openapi-generator-maven-plugin/src/test/resources/unit/common-maven/common-maven.xml
rename to modules/openapi-generator-maven-plugin/src/test/resources/default/pom.xml
index 767caeab2dd..95ab2451e5d 100644
--- a/modules/openapi-generator-maven-plugin/src/test/resources/unit/common-maven/common-maven.xml
+++ b/modules/openapi-generator-maven-plugin/src/test/resources/default/pom.xml
@@ -29,8 +29,7 @@
org.openapitools
openapi-generator-maven-plugin
-
- ${basedir}/src/test/resources/unit/common-maven/petstore.yaml
+ ${basedir}/petstore.yaml
java
joda
@@ -43,7 +42,7 @@
- default
+ executionId
generate-sources
generate
diff --git a/modules/openapi-generator-maven-plugin/src/test/resources/unit/common-maven/src/main/java/com/example/Example.java b/modules/openapi-generator-maven-plugin/src/test/resources/default/src/main/java/com/example/Example.java
similarity index 100%
rename from modules/openapi-generator-maven-plugin/src/test/resources/unit/common-maven/src/main/java/com/example/Example.java
rename to modules/openapi-generator-maven-plugin/src/test/resources/default/src/main/java/com/example/Example.java
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java
index 2e7151dc94e..631ff47eedb 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java
@@ -206,7 +206,7 @@ public class CodegenConstants {
public static final String MODEL_PROPERTY_NAMING_DESC = "Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name";
public static final String DOTNET_FRAMEWORK = "targetFramework";
- public static final String DOTNET_FRAMEWORK_DESC = "The target .NET framework version.";
+ public static final String DOTNET_FRAMEWORK_DESC = "The target .NET framework version. To target multiple frameworks, use `;` as the separator, e.g. `netstandard2.1;netcoreapp3.0`";
public static final String TEMPLATING_ENGINE = "templatingEngine";
public static final String TEMPLATING_ENGINE_DESC = "The templating engine plugin to use: \"mustache\" (default) or \"handlebars\" (beta)";
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java
index b41adac4487..0a8e7b31991 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java
@@ -29,7 +29,7 @@ public class CodegenOperation {
isArray, isMultipart,
isResponseBinary = false, isResponseFile = false, hasReference = false,
isRestfulIndex, isRestfulShow, isRestfulCreate, isRestfulUpdate, isRestfulDestroy,
- isRestful, isDeprecated, isCallbackRequest, uniqueItems;
+ isRestful, isDeprecated, isCallbackRequest, uniqueItems, hasDefaultResponse = false;
public String path, operationId, returnType, returnFormat, httpMethod, returnBaseType,
returnContainer, summary, unescapedNotes, notes, baseName, defaultResponse;
public CodegenDiscriminator discriminator;
@@ -168,6 +168,15 @@ public class CodegenOperation {
return nonempty(examples);
}
+ /**
+ * Check if there's a default response
+ *
+ * @return true if responses contain a default response, false otherwise
+ */
+ public boolean getHasDefaultResponse() {
+ return responses.stream().filter(response -> response.isDefault).findFirst().isPresent();
+ }
+
/**
* Check if act as Restful index method
*
@@ -270,6 +279,7 @@ public class CodegenOperation {
sb.append(", isResponseBinary=").append(isResponseBinary);
sb.append(", isResponseFile=").append(isResponseFile);
sb.append(", hasReference=").append(hasReference);
+ sb.append(", hasDefaultResponse=").append(hasDefaultResponse);
sb.append(", isRestfulIndex=").append(isRestfulIndex);
sb.append(", isRestfulShow=").append(isRestfulShow);
sb.append(", isRestfulCreate=").append(isRestfulCreate);
@@ -343,6 +353,7 @@ public class CodegenOperation {
isResponseBinary == that.isResponseBinary &&
isResponseFile == that.isResponseFile &&
hasReference == that.hasReference &&
+ hasDefaultResponse == that.hasDefaultResponse &&
isRestfulIndex == that.isRestfulIndex &&
isRestfulShow == that.isRestfulShow &&
isRestfulCreate == that.isRestfulCreate &&
@@ -400,7 +411,7 @@ public class CodegenOperation {
return Objects.hash(responseHeaders, hasAuthMethods, hasConsumes, hasProduces, hasParams, hasOptionalParams,
hasRequiredParams, returnTypeIsPrimitive, returnSimpleType, subresourceOperation, isMap,
- isArray, isMultipart, isResponseBinary, isResponseFile, hasReference, isRestfulIndex,
+ isArray, isMultipart, isResponseBinary, isResponseFile, hasReference, hasDefaultResponse, isRestfulIndex,
isRestfulShow, isRestfulCreate, isRestfulUpdate, isRestfulDestroy, isRestful, isDeprecated,
isCallbackRequest, uniqueItems, path, operationId, returnType, httpMethod, returnBaseType,
returnContainer, summary, unescapedNotes, notes, baseName, defaultResponse, discriminator, consumes,
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenSecurity.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenSecurity.java
index ca659105b7f..a5d5bd4ce85 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenSecurity.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenSecurity.java
@@ -39,7 +39,7 @@ public class CodegenSecurity {
public String keyParamName;
public Boolean isKeyInQuery, isKeyInHeader, isKeyInCookie;
// Oauth specific
- public String flow, authorizationUrl, tokenUrl;
+ public String flow, authorizationUrl, tokenUrl, refreshUrl;
public List> scopes;
public Boolean isCode, isPassword, isApplication, isImplicit;
@@ -66,6 +66,7 @@ public class CodegenSecurity {
filteredSecurity.flow = flow;
filteredSecurity.tokenUrl = tokenUrl;
filteredSecurity.authorizationUrl = authorizationUrl;
+ filteredSecurity.refreshUrl = refreshUrl;
// It is not possible to deep copy the extensions, as we have no idea what types they are.
// So the filtered method *will* refer to the original extensions, if any.
filteredSecurity.vendorExtensions = new HashMap(vendorExtensions);
@@ -109,6 +110,7 @@ public class CodegenSecurity {
Objects.equals(flow, that.flow) &&
Objects.equals(authorizationUrl, that.authorizationUrl) &&
Objects.equals(tokenUrl, that.tokenUrl) &&
+ Objects.equals(refreshUrl, that.refreshUrl) &&
Objects.equals(scopes, that.scopes) &&
Objects.equals(isCode, that.isCode) &&
Objects.equals(isPassword, that.isPassword) &&
@@ -122,7 +124,7 @@ public class CodegenSecurity {
return Objects.hash(name, type, scheme, isBasic, isOAuth, isApiKey,
isBasicBasic, isHttpSignature, isBasicBearer, bearerFormat, vendorExtensions,
keyParamName, isKeyInQuery, isKeyInHeader, isKeyInCookie, flow,
- authorizationUrl, tokenUrl, scopes, isCode, isPassword, isApplication, isImplicit);
+ authorizationUrl, tokenUrl, refreshUrl, scopes, isCode, isPassword, isApplication, isImplicit);
}
@Override
@@ -146,6 +148,7 @@ public class CodegenSecurity {
sb.append(", flow='").append(flow).append('\'');
sb.append(", authorizationUrl='").append(authorizationUrl).append('\'');
sb.append(", tokenUrl='").append(tokenUrl).append('\'');
+ sb.append(", refreshUrl='").append(refreshUrl).append('\'');
sb.append(", scopes=").append(scopes);
sb.append(", isCode=").append(isCode);
sb.append(", isPassword=").append(isPassword);
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java
index 590e925a142..2edf1bf15af 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java
@@ -2043,6 +2043,10 @@ public class DefaultCodegen implements CodegenConfig {
private String getPrimitiveType(Schema schema) {
if (schema == null) {
throw new RuntimeException("schema cannot be null in getPrimitiveType");
+ } else if (typeMapping.containsKey(schema.getType() + "+" + schema.getFormat())) {
+ // allows custom type_format mapping.
+ // use {type}+{format}
+ return typeMapping.get(schema.getType() + "+" + schema.getFormat());
} else if (ModelUtils.isNullType(schema)) {
// The 'null' type is allowed in OAS 3.1 and above. It is not supported by OAS 3.0.x,
// though this tooling supports it.
@@ -2702,14 +2706,14 @@ public class DefaultCodegen implements CodegenConfig {
String modelName = ModelUtils.getSimpleRef(oneOf.get$ref());
CodegenProperty thisCp = discriminatorFound(composedSchemaName, oneOf, discPropName, openAPI);
if (thisCp == null) {
- throw new RuntimeException("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the referenced OneOf schema '" + modelName + "' is missing " + discPropName);
+ LOGGER.warn("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the referenced OneOf schema '" + modelName + "' is missing " + discPropName);
}
if (cp.dataType == null) {
cp = thisCp;
continue;
}
if (cp != thisCp) {
- throw new RuntimeException("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the OneOf schema '" + modelName + "' has a different " + discPropName + " definition than the prior OneOf schema's. Make sure the " + discPropName + " type and required values are the same");
+ LOGGER.warn("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the OneOf schema '" + modelName + "' has a different " + discPropName + " definition than the prior OneOf schema's. Make sure the " + discPropName + " type and required values are the same");
}
}
return cp;
@@ -2721,14 +2725,14 @@ public class DefaultCodegen implements CodegenConfig {
String modelName = ModelUtils.getSimpleRef(anyOf.get$ref());
CodegenProperty thisCp = discriminatorFound(composedSchemaName, anyOf, discPropName, openAPI);
if (thisCp == null) {
- throw new RuntimeException("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the referenced AnyOf schema '" + modelName + "' is missing " + discPropName);
+ LOGGER.warn("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the referenced AnyOf schema '" + modelName + "' is missing " + discPropName);
}
if (cp.dataType == null) {
cp = thisCp;
continue;
}
if (cp != thisCp) {
- throw new RuntimeException("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the AnyOf schema '" + modelName + "' has a different " + discPropName + " definition than the prior AnyOf schema's. Make sure the " + discPropName + " type and required values are the same");
+ LOGGER.warn("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the AnyOf schema '" + modelName + "' has a different " + discPropName + " definition than the prior AnyOf schema's. Make sure the " + discPropName + " type and required values are the same");
}
}
return cp;
@@ -2787,7 +2791,7 @@ public class DefaultCodegen implements CodegenConfig {
}
}
if (discriminatorsPropNames.size() > 1) {
- throw new RuntimeException("The oneOf schemas have conflicting discriminator property names. " +
+ LOGGER.warn("The oneOf schemas have conflicting discriminator property names. " +
"oneOf schemas must have the same property name, but found " + String.join(", ", discriminatorsPropNames));
}
if (foundDisc != null && (hasDiscriminatorCnt + hasNullTypeCnt) == composedSchema.getOneOf().size() && discriminatorsPropNames.size() == 1) {
@@ -2816,7 +2820,7 @@ public class DefaultCodegen implements CodegenConfig {
}
}
if (discriminatorsPropNames.size() > 1) {
- throw new RuntimeException("The anyOf schemas have conflicting discriminator property names. " +
+ LOGGER.warn("The anyOf schemas have conflicting discriminator property names. " +
"anyOf schemas must have the same property name, but found " + String.join(", ", discriminatorsPropNames));
}
if (foundDisc != null && (hasDiscriminatorCnt + hasNullTypeCnt) == composedSchema.getAnyOf().size() && discriminatorsPropNames.size() == 1) {
@@ -2866,7 +2870,7 @@ public class DefaultCodegen implements CodegenConfig {
// schemas also has inline composed schemas
// Note: if it is only inline one level, then the inline model resolver will move it into its own
// schema and make it a $ref schema in the oneOf/anyOf location
- throw new RuntimeException("Invalid inline schema defined in oneOf/anyOf in '" + composedSchemaName + "'. Per the OpenApi spec, for this case when a composed schema defines a discriminator, the oneOf/anyOf schemas must use $ref. Change this inline definition to a $ref definition");
+ LOGGER.warn("Invalid inline schema defined in oneOf/anyOf in '" + composedSchemaName + "'. Per the OpenApi spec, for this case when a composed schema defines a discriminator, the oneOf/anyOf schemas must use $ref. Change this inline definition to a $ref definition");
}
CodegenProperty df = discriminatorFound(composedSchemaName, sc, discPropName, openAPI);
String modelName = ModelUtils.getSimpleRef(ref);
@@ -2886,7 +2890,7 @@ public class DefaultCodegen implements CodegenConfig {
msgSuffix += spacer + "invalid optional definition of " + discPropName + ", include it in required";
}
}
- throw new RuntimeException("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the referenced schema '" + modelName + "' is incorrect. " + msgSuffix);
+ LOGGER.warn("'" + composedSchemaName + "' defines discriminator '" + discPropName + "', but the referenced schema '" + modelName + "' is incorrect. " + msgSuffix);
}
MappedModel mm = new MappedModel(modelName, toModelName(modelName));
descendentSchemas.add(mm);
@@ -5599,6 +5603,7 @@ public class DefaultCodegen implements CodegenConfig {
private void setOauth2Info(CodegenSecurity codegenSecurity, OAuthFlow flow) {
codegenSecurity.authorizationUrl = flow.getAuthorizationUrl();
codegenSecurity.tokenUrl = flow.getTokenUrl();
+ codegenSecurity.refreshUrl = flow.getRefreshUrl();
if (flow.getScopes() != null && !flow.getScopes().isEmpty()) {
List> scopes = new ArrayList<>();
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java
index 2782357482c..eb263b34c37 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java
@@ -576,7 +576,7 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
var.isString = false;
var.isLong = false;
var.isInteger = false;
- } else if ("int32".equals(var.dataFormat)) {
+ } else if ("int".equals(var.dataType) || "int32".equals(var.dataFormat)) {
var.isInteger = true;
var.isString = false;
var.isLong = false;
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java
index 6f320377c52..6cd5d2926e8 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java
@@ -1,6 +1,7 @@
package org.openapitools.codegen.languages;
import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.ArraySchema;
@@ -51,9 +52,7 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
protected String apiTestPath = "test" + File.separator;
protected String modelTestPath = "test" + File.separator;
- // Names that must not be used as model names because they clash with existing
- // default imports (dart:io, dart:async, package:http etc.) but are not basic dataTypes.
- protected Set additionalReservedWords;
+ protected Map imports = new HashMap<>();
public AbstractDartCodegen() {
super();
@@ -112,13 +111,13 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
}
setReservedWordsLowerCase(reservedWordsList);
+ // These types return isPrimitive=true in templates
languageSpecificPrimitives = Sets.newHashSet(
"String",
"bool",
"int",
"num",
- "double",
- "dynamic"
+ "double"
);
typeMapping = new HashMap<>();
@@ -149,29 +148,31 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
typeMapping.put("object", "Object");
typeMapping.put("AnyType", "Object");
- // DataTypes of the above values which are automatically imported.
- // They are also not allowed to be model names.
+ // Data types of the above values which are automatically imported
defaultIncludes = Sets.newHashSet(
"String",
"bool",
"int",
"num",
"double",
- "dynamic",
"List",
"Set",
"Map",
"DateTime",
- "Object",
- "MultipartFile"
+ "Object"
);
- additionalReservedWords = Sets.newHashSet(
- "File",
- "Client",
- "Future",
- "Response"
- );
+ imports.put("String", "dart:core");
+ imports.put("bool", "dart:core");
+ imports.put("int", "dart:core");
+ imports.put("num", "dart:core");
+ imports.put("double", "dart:core");
+ imports.put("List", "dart:core");
+ imports.put("Set", "dart:core");
+ imports.put("Map", "dart:core");
+ imports.put("DateTime", "dart:core");
+ imports.put("Object", "dart:core");
+ imports.put("MultipartFile", "package:http/http.dart");
cliOptions.add(new CliOption(PUB_LIBRARY, "Library name in generated code"));
cliOptions.add(new CliOption(PUB_NAME, "Name in generated pubspec"));
@@ -182,7 +183,6 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
cliOptions.add(new CliOption(PUB_HOMEPAGE, "Homepage in generated pubspec"));
cliOptions.add(new CliOption(USE_ENUM_EXTENSION, "Allow the 'x-enum-values' extension for enums"));
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, "Source folder for generated code"));
-
}
@Override
@@ -279,13 +279,17 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
}
}
+ @Override
+ protected boolean needToImport(String type) {
+ // Import everything, unless it is from dart:core.
+ return StringUtils.isNotBlank(type) && (!imports.containsKey(type) || !imports.get(type).equals("dart:core"));
+ }
+
@Override
protected boolean isReservedWord(String word) {
// consider everything as reserved that is either a keyword,
// a default included type, or a type include through some library
- return super.isReservedWord(word) ||
- defaultIncludes().contains(word) ||
- additionalReservedWords.contains(word);
+ return super.isReservedWord(word) || defaultIncludes().contains(word);
}
@Override
@@ -367,20 +371,34 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
@Override
public String toModelName(final String name) {
- String nameWithPrefixSuffix = sanitizeName(name);
+ String sanitizedName = sanitizeName(name);
+
if (!StringUtils.isEmpty(modelNamePrefix)) {
// add '_' so that model name can be camelized correctly
- nameWithPrefixSuffix = modelNamePrefix + "_" + nameWithPrefixSuffix;
+ sanitizedName = modelNamePrefix + "_" + sanitizedName;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
// add '_' so that model name can be camelized correctly
- nameWithPrefixSuffix = nameWithPrefixSuffix + "_" + modelNameSuffix;
+ sanitizedName = sanitizedName + "_" + modelNameSuffix;
}
// camelize the model name
// phone_number => PhoneNumber
- final String camelizedName = camelize(nameWithPrefixSuffix);
+ final String camelizedName = camelize(sanitizedName);
+
+ // Check if there is a mapping that can be used
+ if (typeMapping().containsKey(camelizedName)) {
+ String typeName = typeMapping().get(camelizedName);
+ if (imports.containsKey(typeName)) {
+ // Anything with an import mapping is likely
+ // generator specific and can not be used as model name.
+ final String modelName = "Model" + camelizedName;
+ LOGGER.warn("{} (existing type) cannot be used as model name. Renamed to {}", camelizedName, modelName);
+ return modelName;
+ }
+ return typeName;
+ }
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(camelizedName)) {
@@ -473,11 +491,8 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
if (openAPIType == null) {
LOGGER.error("No Type defined for Schema {}", p);
}
- if (typeMapping.containsKey(openAPIType)) {
- return typeMapping.get(openAPIType);
- }
- if (languageSpecificPrimitives.contains(openAPIType)) {
- return openAPIType;
+ if (typeMapping().containsKey(openAPIType)) {
+ return typeMapping().get(openAPIType);
}
return toModelName(openAPIType);
}
@@ -607,8 +622,9 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
// operationId starts with a number
if (operationId.matches("^\\d.*")) {
- LOGGER.warn("{} (starting with a number) cannot be used as method name. Renamed to {}", operationId, camelize("call_" + operationId), true);
- operationId = camelize("call_" + operationId, true);
+ String newOperationId = camelize("call_" + operationId, true);
+ LOGGER.warn("{} (starting with a number) cannot be used as method name. Renamed to {}", operationId, newOperationId);
+ operationId = newOperationId;
}
return operationId;
@@ -692,33 +708,4 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
}
}
}
-
- @Override
- public void postProcess() {
- if (isEnablePostProcessFile()) {
- // Using the condition here to have way to still disable this
- // for older Dart generators in CI by default.
-
- // Post processing the whole dart output is much faster then individual files.
- // Setting this variable to "dart format" is the suggested way of doing this.
- final String dartPostProcess = System.getenv("DART_POST_PROCESS");
- if (!StringUtils.isEmpty(dartPostProcess)) {
- final String command = dartPostProcess + " " + getOutputDir();
- try {
- Process p = Runtime.getRuntime().exec(command);
- int exitValue = p.waitFor();
- if (exitValue != 0) {
- LOGGER.error("Error running the command ({}). Exit code: {}", command, exitValue);
- } else {
- LOGGER.info("Successfully executed: {}", command);
- }
- } catch (InterruptedException | IOException e) {
- LOGGER.error("Error running the command ({}). Exception: {}", command, e.getMessage());
- // Restore interrupted state
- Thread.currentThread().interrupt();
- }
- }
- }
- super.postProcess();
- }
}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java
index e45bc2ef3fe..cee83d467c8 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java
@@ -311,16 +311,17 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege
@Override
public String toApiFilename(String name) {
+ final String apiName;
// replace - with _ e.g. created-at => created_at
- name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
-
+ String api = name.replaceAll("-", "_");
// e.g. PetApi.go => pet_api.go
- name = "api_" + underscore(name);
- if (isReservedFilename(name)) {
- LOGGER.warn(name + ".go with suffix (reserved word) cannot be used as filename. Renamed to " + name + "_.go");
- name += "_";
+ api = "api_" + underscore(api);
+ if (isReservedFilename(api)) {
+ LOGGER.warn(name + ".go with suffix (reserved word) cannot be used as filename. Renamed to " + api + "_.go");
+ api += "_";
}
- return name;
+ apiName = api;
+ return apiName;
}
/**
@@ -807,7 +808,7 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege
return; // skip if GO_POST_PROCESS_FILE env variable is not defined
}
- // only procees the following type (or we can simply rely on the file extension to check if it's a Go file)
+ // only process the following type (or we can simply rely on the file extension to check if it's a Go file)
Set supportedFileType = new HashSet(
Arrays.asList(
"supporting-mustache",
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java
index be64dde62f1..ff90d1e30e2 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java
@@ -590,38 +590,51 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
throw new RuntimeException("Invalid HTTP library " + getLibrary() + ". Only restsharp, httpclient are supported.");
}
- String framework = (String) additionalProperties.getOrDefault(CodegenConstants.DOTNET_FRAMEWORK, defaultFramework.name);
- boolean strategyMatched = false;
- FrameworkStrategy strategy = defaultFramework;
- for (FrameworkStrategy frameworkStrategy : frameworkStrategies) {
- if (framework.equals(frameworkStrategy.name)) {
- strategy = frameworkStrategy;
- strategyMatched = true;
+ String inputFramework = (String) additionalProperties.getOrDefault(CodegenConstants.DOTNET_FRAMEWORK, defaultFramework.name);
+ String[] frameworks;
+ List strategies = new ArrayList<>();
+
+ if (inputFramework.contains(";")) {
+ // multiple target framework
+ frameworks = inputFramework.split(";");
+ additionalProperties.put("multiTarget", true);
+ } else {
+ // just a single value
+ frameworks = new String [] {inputFramework};
+ }
+
+ for (String framework : frameworks) {
+ boolean strategyMatched = false;
+ for (FrameworkStrategy frameworkStrategy : frameworkStrategies) {
+ if (framework.equals(frameworkStrategy.name)) {
+ strategies.add(frameworkStrategy);
+ strategyMatched = true;
+ }
+
+ if (frameworkStrategy != FrameworkStrategy.NETSTANDARD_2_0 && "restsharp".equals(getLibrary())) {
+ LOGGER.warn("If using built-in templates, RestSharp only supports netstandard 2.0 or later.");
+ }
+ }
+
+ if (!strategyMatched) {
+ // throws exception if the input targetFramework is invalid
+ throw new IllegalArgumentException("The input (" + inputFramework + ") contains Invalid .NET framework version: " +
+ framework + ". List of supported versions: " +
+ frameworkStrategies.stream()
+ .map(p -> p.name)
+ .collect(Collectors.joining(", ")));
}
}
- // throws exception if the input targetFramework is invalid
- if (strategyMatched == false) {
- throw new IllegalArgumentException("Invalid .NET framework version: " +
- framework + ". List of supported versions: " +
- frameworkStrategies.stream()
- .map(p -> p.name)
- .collect(Collectors.joining(", ")));
- }
-
- strategy.configureAdditionalProperties(additionalProperties);
- setTargetFrameworkNuget(strategy.getNugetFrameworkIdentifier());
- setTargetFramework(strategy.name);
- setTestTargetFramework(strategy.testTargetFramework);
-
- if (strategy != FrameworkStrategy.NETSTANDARD_2_0) {
- LOGGER.warn("If using built-in templates-RestSharp only supports netstandard 2.0 or later.");
- }
+ configureAdditionalPropertiesForFrameworks(additionalProperties, strategies);
+ setTargetFrameworkNuget(strategies);
+ setTargetFramework(strategies);
+ setTestTargetFramework(strategies);
setSupportsAsync(Boolean.TRUE);
- setNetStandard(strategy.isNetStandard);
+ setNetStandard(strategies.stream().anyMatch(p -> Boolean.TRUE.equals(p.isNetStandard)));
- if (!strategy.isNetStandard) {
+ if (!netStandard) {
setNetCoreProjectFileFlag(true);
}
@@ -774,14 +787,39 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
LOGGER.info("Generating code for .NET Framework " + this.targetFramework);
}
+ public void setTargetFramework(List strategies) {
+ for (FrameworkStrategy strategy : strategies) {
+ if (!frameworks.containsKey(strategy.name)) {
+ throw new IllegalArgumentException("Invalid .NET framework version: " +
+ strategy.name + ". List of supported versions: " +
+ frameworkStrategies.stream()
+ .map(p -> p.name)
+ .collect(Collectors.joining(", ")));
+ }
+ }
+ this.targetFramework = strategies.stream().map(p -> p.name)
+ .collect(Collectors.joining(";"));
+ LOGGER.info("Generating code for .NET Framework " + this.targetFramework);
+ }
+
public void setTestTargetFramework(String testTargetFramework) {
this.testTargetFramework = testTargetFramework;
}
+ public void setTestTargetFramework(List strategies) {
+ this.testTargetFramework = strategies.stream().map(p -> p.testTargetFramework)
+ .collect(Collectors.joining(";"));
+ }
+
public void setTargetFrameworkNuget(String targetFrameworkNuget) {
this.targetFrameworkNuget = targetFrameworkNuget;
}
+ public void setTargetFrameworkNuget(List strategies) {
+ this.targetFrameworkNuget = strategies.stream().map(p -> p.getNugetFrameworkIdentifier())
+ .collect(Collectors.joining(";"));
+ }
+
public void setValidatable(boolean validatable) {
this.validatable = validatable;
}
@@ -1003,6 +1041,23 @@ public class CSharpNetCoreClientCodegen extends AbstractCSharpCodegen {
}
}
+ protected void configureAdditionalPropertiesForFrameworks(final Map properties, List strategies) {
+ properties.putIfAbsent(CodegenConstants.DOTNET_FRAMEWORK, strategies.stream()
+ .map(p -> p.name)
+ .collect(Collectors.joining(";")));
+
+ // not intended to be user-settable
+ properties.put(TARGET_FRAMEWORK_IDENTIFIER, strategies.stream()
+ .map(p -> p.getTargetFrameworkIdentifier())
+ .collect(Collectors.joining(";")));
+ properties.put(TARGET_FRAMEWORK_VERSION, strategies.stream()
+ .map(p -> p.getTargetFrameworkVersion())
+ .collect(Collectors.joining(";")));
+ properties.putIfAbsent(MCS_NET_VERSION_KEY, "4.6-api");
+
+ properties.put(NET_STANDARD, strategies.stream().anyMatch(p -> Boolean.TRUE.equals(p.isNetStandard)));
+ }
+
/**
* Return the instantiation type of the property, especially for map and array
*
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartClientCodegen.java
index 59578099cce..589ef137f34 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartClientCodegen.java
@@ -37,20 +37,6 @@ public class DartClientCodegen extends AbstractDartCodegen {
public DartClientCodegen() {
super();
-
- additionalReservedWords.addAll(
- Sets.newHashSet(
- "StreamedRequest",
- "ApiClient",
- "QueryParam",
- "Authentication",
- "HttpBasicAuth",
- "HttpBearerAuth",
- "ApiKeyAuth",
- "OAuth"
- )
- );
-
final CliOption serializationLibrary = CliOption.newString(CodegenConstants.SERIALIZATION_LIBRARY,
"Specify serialization library");
serializationLibrary.setDefault(SERIALIZATION_LIBRARY_NATIVE);
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java
index a0bafd5e8ac..23b50b2f756 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java
@@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
+import java.util.stream.Collectors;
import static org.openapitools.codegen.utils.StringUtils.underscore;
@@ -77,22 +78,11 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
typeMapping.put("object", "JsonObject");
typeMapping.put("AnyType", "JsonObject");
- additionalReservedWords.addAll(Sets.newHashSet(
- "EnumClass",
- // The following are reserved dataTypes but can not be added to defaultIncludes
- // as this would prevent them from being added to the imports.
- "BuiltList",
- "BuiltSet",
- "BuiltMap",
- "Uint8List",
- "JsonObject"
- ));
-
- importMapping.put("BuiltList", "package:built_collection/built_collection.dart");
- importMapping.put("BuiltSet", "package:built_collection/built_collection.dart");
- importMapping.put("BuiltMap", "package:built_collection/built_collection.dart");
- importMapping.put("JsonObject", "package:built_value/json_object.dart");
- importMapping.put("Uint8List", "dart:typed_data");
+ imports.put("BuiltList", "package:built_collection/built_collection.dart");
+ imports.put("BuiltSet", "package:built_collection/built_collection.dart");
+ imports.put("BuiltMap", "package:built_collection/built_collection.dart");
+ imports.put("JsonObject", "package:built_value/json_object.dart");
+ imports.put("Uint8List", "dart:typed_data");
}
public String getDateLibrary() {
@@ -210,9 +200,8 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
typeMapping.put("Date", "OffsetDate");
typeMapping.put("DateTime", "OffsetDateTime");
typeMapping.put("datetime", "OffsetDateTime");
- additionalReservedWords.addAll(Sets.newHashSet("OffsetDate", "OffsetDateTime"));
- importMapping.put("OffsetDate", "package:time_machine/time_machine.dart");
- importMapping.put("OffsetDateTime", "package:time_machine/time_machine.dart");
+ imports.put("OffsetDate", "package:time_machine/time_machine.dart");
+ imports.put("OffsetDateTime", "package:time_machine/time_machine.dart");
supportingFiles.add(new SupportingFile("local_date_serializer.mustache", libFolder, "local_date_serializer.dart"));
}
}
@@ -225,21 +214,9 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
for (Object _mo : models) {
Map mo = (Map) _mo;
- Set modelImports = new HashSet<>();
CodegenModel cm = (CodegenModel) mo.get("model");
- for (String modelImport : cm.imports) {
- if (needToImport(modelImport)) {
- if (importMapping().containsKey(modelImport)) {
- modelImports.add(importMapping().get(modelImport));
- } else {
- modelImports.add("package:" + pubName + "/model/" + underscore(modelImport) + ".dart");
- }
- }
- }
-
- cm.imports = modelImports;
- boolean hasVars = cm.vars.size() > 0;
- cm.vendorExtensions.put("x-has-vars", hasVars);
+ cm.imports = rewriteImports(cm.imports);
+ cm.vendorExtensions.put("x-has-vars", !cm.vars.isEmpty());
}
return objs;
}
@@ -292,8 +269,7 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
List operationList = (List) operations.get("operation");
Set> serializers = new HashSet<>();
- Set modelImports = new HashSet<>();
- Set fullImports = new HashSet<>();
+ Set resultImports = new HashSet<>();
for (CodegenOperation op : operationList) {
op.httpMethod = op.httpMethod.toLowerCase(Locale.ROOT);
@@ -331,23 +307,11 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
op.vendorExtensions.put("x-is-form", isForm);
op.vendorExtensions.put("x-is-multipart", isMultipart);
+ resultImports.addAll(rewriteImports(op.imports));
if (op.getHasFormParams()) {
- fullImports.add("package:" + pubName + "/api_util.dart");
+ resultImports.add("package:" + pubName + "/api_util.dart");
}
- Set imports = new HashSet<>();
- for (String item : op.imports) {
- if (needToImport(item)) {
- if (importMapping().containsKey(item)) {
- fullImports.add(importMapping().get(item));
- } else {
- imports.add(underscore(item));
- }
- }
- }
- modelImports.addAll(imports);
- op.imports = imports;
-
if (op.returnContainer != null) {
final Map serializer = new HashMap<>();
serializer.put("isArray", Objects.equals("array", op.returnContainer) || Objects.equals("set", op.returnContainer));
@@ -358,11 +322,21 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
}
}
- objs.put("modelImports", modelImports);
- objs.put("fullImports", fullImports);
+ objs.put("imports", resultImports.stream().sorted().collect(Collectors.toList()));
objs.put("serializers", serializers);
return objs;
}
+ private Set rewriteImports(Set originalImports) {
+ Set resultImports = Sets.newHashSet();
+ for (String modelImport : originalImports) {
+ if (imports.containsKey(modelImport)) {
+ resultImports.add(imports.get(modelImport));
+ } else {
+ resultImports.add("package:" + pubName + "/model/" + underscore(modelImport) + ".dart");
+ }
+ }
+ return resultImports;
+ }
}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioNextClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioNextClientCodegen.java
index 7034bc4bece..764c1146426 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioNextClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioNextClientCodegen.java
@@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
+import java.util.stream.Collectors;
import static org.openapitools.codegen.utils.StringUtils.underscore;
@@ -186,22 +187,11 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
typeMapping.put("object", "JsonObject");
typeMapping.put("AnyType", "JsonObject");
- additionalReservedWords.addAll(Sets.newHashSet(
- "EnumClass",
- // The following are reserved dataTypes but can not be added to defaultIncludes
- // as this would prevent them from being added to the imports.
- "BuiltList",
- "BuiltSet",
- "BuiltMap",
- "Uint8List",
- "JsonObject"
- ));
-
- importMapping.put("BuiltList", "package:built_collection/built_collection.dart");
- importMapping.put("BuiltSet", "package:built_collection/built_collection.dart");
- importMapping.put("BuiltMap", "package:built_collection/built_collection.dart");
- importMapping.put("JsonObject", "package:built_value/json_object.dart");
- importMapping.put("Uint8List", "dart:typed_data");
+ imports.put("BuiltList", "package:built_collection/built_collection.dart");
+ imports.put("BuiltSet", "package:built_collection/built_collection.dart");
+ imports.put("BuiltMap", "package:built_collection/built_collection.dart");
+ imports.put("JsonObject", "package:built_value/json_object.dart");
+ imports.put("Uint8List", "dart:typed_data");
}
private void configureDateLibrary(String srcFolder) {
@@ -212,17 +202,22 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
typeMapping.put("Date", "OffsetDate");
typeMapping.put("DateTime", "OffsetDateTime");
typeMapping.put("datetime", "OffsetDateTime");
- additionalReservedWords.addAll(Sets.newHashSet("OffsetDate", "OffsetDateTime"));
- importMapping.put("OffsetDate", "package:time_machine/time_machine.dart");
- importMapping.put("OffsetDateTime", "package:time_machine/time_machine.dart");
+ imports.put("OffsetDate", "package:time_machine/time_machine.dart");
+ imports.put("OffsetDateTime", "package:time_machine/time_machine.dart");
if (SERIALIZATION_LIBRARY_BUILT_VALUE.equals(library)) {
- supportingFiles.add(new SupportingFile("serialization/built_value/local_date_serializer.mustache", srcFolder, "local_date_serializer.dart"));
+ supportingFiles.add(new SupportingFile("serialization/built_value/offset_date_serializer.mustache", srcFolder, "local_date_serializer.dart"));
}
break;
default:
case DATE_LIBRARY_CORE:
- // this option uses the dart core classes
additionalProperties.put("useDateLibCore", "true");
+ if (SERIALIZATION_LIBRARY_BUILT_VALUE.equals(library)) {
+ typeMapping.put("date", "Date");
+ typeMapping.put("Date", "Date");
+ importMapping.put("Date", "package:" + pubName + "/src/model/date.dart");
+ supportingFiles.add(new SupportingFile("serialization/built_value/date.mustache", srcFolder + File.separator + "model", "date.dart"));
+ supportingFiles.add(new SupportingFile("serialization/built_value/date_serializer.mustache", srcFolder, "date_serializer.dart"));
+ }
break;
}
}
@@ -261,21 +256,9 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
for (Object _mo : models) {
Map mo = (Map) _mo;
- Set modelImports = new HashSet<>();
CodegenModel cm = (CodegenModel) mo.get("model");
- for (String modelImport : cm.imports) {
- if (needToImport(modelImport)) {
- if (importMapping().containsKey(modelImport)) {
- modelImports.add(importMapping().get(modelImport));
- } else {
- modelImports.add("package:" + pubName + "/src/model/" + underscore(modelImport) + ".dart");
- }
- }
- }
-
- cm.imports = modelImports;
- boolean hasVars = cm.vars.size() > 0;
- cm.vendorExtensions.put("x-has-vars", hasVars);
+ cm.imports = rewriteImports(cm.imports);
+ cm.vendorExtensions.put("x-has-vars", !cm.vars.isEmpty());
}
return objs;
}
@@ -319,6 +302,7 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
sb.append(")]");
}
+
@Override
public Map postProcessOperationsWithModels(Map objs, List allModels) {
objs = super.postProcessOperationsWithModels(objs, allModels);
@@ -326,8 +310,7 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
List operationList = (List) operations.get("operation");
Set> serializers = new HashSet<>();
- Set modelImports = new HashSet<>();
- Set fullImports = new HashSet<>();
+ Set resultImports = new HashSet<>();
for (CodegenOperation op : operationList) {
op.httpMethod = op.httpMethod.toLowerCase(Locale.ROOT);
@@ -365,23 +348,11 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
op.vendorExtensions.put("x-is-form", isForm);
op.vendorExtensions.put("x-is-multipart", isMultipart);
+ resultImports.addAll(rewriteImports(op.imports));
if (op.getHasFormParams()) {
- fullImports.add("package:" + pubName + "/src/api_util.dart");
+ resultImports.add("package:" + pubName + "/src/api_util.dart");
}
- Set imports = new HashSet<>();
- for (String item : op.imports) {
- if (needToImport(item)) {
- if (importMapping().containsKey(item)) {
- fullImports.add(importMapping().get(item));
- } else {
- imports.add(underscore(item));
- }
- }
- }
- modelImports.addAll(imports);
- op.imports = imports;
-
if (op.returnContainer != null) {
final Map serializer = new HashMap<>();
serializer.put("isArray", Objects.equals("array", op.returnContainer) || Objects.equals("set", op.returnContainer));
@@ -392,11 +363,21 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
}
}
- objs.put("modelImports", modelImports);
- objs.put("fullImports", fullImports);
+ objs.put("imports", resultImports.stream().sorted().collect(Collectors.toList()));
objs.put("serializers", serializers);
return objs;
}
+ private Set rewriteImports(Set originalImports) {
+ Set resultImports = Sets.newHashSet();
+ for (String modelImport : originalImports) {
+ if (imports.containsKey(modelImport)) {
+ resultImports.add(imports.get(modelImport));
+ } else {
+ resultImports.add("package:" + pubName + "/src/model/" + underscore(modelImport) + ".dart");
+ }
+ }
+ return resultImports;
+ }
}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/FsharpGiraffeServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/FsharpGiraffeServerCodegen.java
index d8d4f7fa3df..b62591c1d0e 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/FsharpGiraffeServerCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/FsharpGiraffeServerCodegen.java
@@ -280,4 +280,17 @@ public class FsharpGiraffeServerCodegen extends AbstractFSharpCodegen {
public String toRegularExpression(String pattern) {
return escapeText(pattern);
}
-}
\ No newline at end of file
+
+ @Override
+ public void postProcess() {
+ System.out.println("################################################################################");
+ System.out.println("# Thanks for using OpenAPI Generator. #");
+ System.out.println("# Please consider donation to help us maintain this project \uD83D\uDE4F #");
+ System.out.println("# https://opencollective.com/openapi_generator/donate #");
+ System.out.println("# #");
+ System.out.println("# This generator's contributed by Nick Fisher (https://github.com/nmfisher) #");
+ System.out.println("# Please support his work directly via https://paypal.me/nickfisher1984 \uD83D\uDE4F #");
+ System.out.println("################################################################################");
+ }
+
+}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoEchoServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoEchoServerCodegen.java
new file mode 100644
index 00000000000..3bd2a37a5e5
--- /dev/null
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoEchoServerCodegen.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openapitools.codegen.languages;
+
+import org.openapitools.codegen.*;
+
+import java.io.File;
+import java.util.*;
+
+import org.openapitools.codegen.meta.features.*;
+import org.openapitools.codegen.meta.GeneratorMetadata;
+import org.openapitools.codegen.meta.Stability;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GoEchoServerCodegen extends AbstractGoCodegen {
+ static final Logger LOGGER = LoggerFactory.getLogger(GoEchoServerCodegen.class);
+
+ protected String apiVersion = "1.0.0";
+ protected int serverPort = 8080;
+ protected String projectName = "openapi-go-echo-server";
+ protected String apiPath = "go";
+
+ private static final String MODEL_PACKAGE_NAME = "models";
+ private static final String API_PACKAGE_NAME = "handlers";
+ private static final String OUTPUT_PATH = "generated-code" + File.separator + "go-echo-server";
+
+ public CodegenType getTag() {
+ return CodegenType.SERVER;
+ }
+
+ public String getName() {
+ return "go-echo-server";
+ }
+
+ public String getHelp() {
+ return "Generates a go-echo server. (Beta)";
+ }
+
+ public GoEchoServerCodegen() {
+ super();
+
+ generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
+ .stability(Stability.BETA)
+ .build();
+
+ modifyFeatureSet(features -> features
+ .includeDocumentationFeatures(DocumentationFeature.Readme)
+ .wireFormatFeatures(EnumSet.of(WireFormatFeature.JSON, WireFormatFeature.XML))
+ .securityFeatures(EnumSet.noneOf(
+ SecurityFeature.class
+ ))
+ .excludeGlobalFeatures(
+ GlobalFeature.XMLStructureDefinitions,
+ GlobalFeature.Callbacks,
+ GlobalFeature.LinkObjects,
+ GlobalFeature.ParameterStyling
+ )
+ .excludeSchemaSupportFeatures(
+ SchemaSupportFeature.Polymorphism
+ )
+ .excludeParameterFeatures(
+ ParameterFeature.Cookie
+ )
+ );
+
+ outputFolder = OUTPUT_PATH;
+ modelTemplateFiles.put("model.mustache", ".go");
+ setModelPackage(MODEL_PACKAGE_NAME);
+ apiTemplateFiles.put("api.mustache", ".go");
+ embeddedTemplateDir = templateDir = "go-echo-server";
+
+ /*
+ * Reserved words. Override this with reserved words specific to your language
+ */
+ setReservedWordsLowerCase(
+ Arrays.asList(
+ // data type
+ "string", "bool", "uint", "uint8", "uint16", "uint32", "uint64",
+ "int", "int8", "int16", "int32", "int64", "float32", "float64",
+ "complex64", "complex128", "rune", "byte", "uintptr",
+ "break", "default", "func", "interface", "select",
+ "case", "defer", "go", "map", "struct",
+ "chan", "else", "goto", "package", "switch",
+ "const", "fallthrough", "if", "range", "type",
+ "continue", "for", "import", "return", "var", "error", "nil")
+ // Added "error" as it's used so frequently that it may as well be a keyword
+ );
+
+ CliOption optServerPort = new CliOption("serverPort", "The network port the generated server binds to");
+ optServerPort.setType("int");
+ optServerPort.defaultValue(Integer.toString(serverPort));
+ cliOptions.add(optServerPort);
+ }
+
+ @Override
+ public Map postProcessOperationsWithModels(Map objs, List allModels) {
+ objs = super.postProcessOperationsWithModels(objs, allModels);
+
+ Map operations = (Map) objs.get("operations");
+ List operationList = (List) operations.get("operation");
+ for (CodegenOperation op : operationList) {
+ if (op.path != null) {
+ op.path = op.path.replaceAll("\\{(.*?)\\}", ":$1");
+ }
+ }
+ return objs;
+ }
+
+ @Override
+ public void processOpts() {
+ super.processOpts();
+
+ if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
+ setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
+ } else {
+ setPackageName("openapi");
+ additionalProperties.put(CodegenConstants.PACKAGE_NAME, this.packageName);
+ }
+
+ /*
+ * Additional Properties. These values can be passed to the templates and
+ * are available in models, apis, and supporting files
+ */
+ if (additionalProperties.containsKey("apiVersion")) {
+ this.apiVersion = (String) additionalProperties.get("apiVersion");
+ } else {
+ additionalProperties.put("apiVersion", apiVersion);
+ }
+
+ if (additionalProperties.containsKey("serverPort")) {
+ this.serverPort = Integer.parseInt((String) additionalProperties.get("serverPort"));
+ } else {
+ additionalProperties.put("serverPort", serverPort);
+ }
+
+ if (additionalProperties.containsKey("apiPath")) {
+ this.apiPath = (String) additionalProperties.get("apiPath");
+ } else {
+ additionalProperties.put("apiPath", apiPath);
+ }
+
+ if (additionalProperties.containsKey(CodegenConstants.ENUM_CLASS_PREFIX)) {
+ setEnumClassPrefix(Boolean.parseBoolean(additionalProperties.get(CodegenConstants.ENUM_CLASS_PREFIX).toString()));
+ if (enumClassPrefix) {
+ additionalProperties.put(CodegenConstants.ENUM_CLASS_PREFIX, true);
+ }
+ }
+
+ /*
+ set model and package names, this is mainly used inside the templates.
+ */
+ modelPackage = MODEL_PACKAGE_NAME;
+ apiPackage = API_PACKAGE_NAME;
+
+ /*
+ * Supporting Files. You can write single files for the generator with the
+ * entire object tree available. If the input file has a suffix of `.mustache
+ * it will be processed by the template engine. Otherwise, it will be copied
+ */
+ supportingFiles.add(new SupportingFile("openapi.mustache", ".docs/api", "openapi.yaml"));
+ supportingFiles.add(new SupportingFile("hello-world.mustache", "models", "hello-world.go"));
+ supportingFiles.add(new SupportingFile("go-mod.mustache", "", "go.mod"));
+ supportingFiles.add(new SupportingFile("handler-container.mustache", "handlers", "container.go"));
+ supportingFiles.add(new SupportingFile("main.mustache", "", "main.go"));
+ supportingFiles.add(new SupportingFile("Dockerfile.mustache", "", "Dockerfile"));
+ supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")
+ .doNotOverwrite());
+ }
+}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java
index 2e08cb6f39d..a0f76b8c299 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java
@@ -37,6 +37,7 @@ public class GoServerCodegen extends AbstractGoCodegen {
protected String projectName = "openapi-server";
protected String sourceFolder = "go";
protected Boolean corsFeatureEnabled = false;
+ protected Boolean addResponseHeaders = false;
public GoServerCodegen() {
@@ -80,6 +81,12 @@ public class GoServerCodegen extends AbstractGoCodegen {
cliOptions.add(CliOption.newBoolean(CodegenConstants.ENUM_CLASS_PREFIX, CodegenConstants.ENUM_CLASS_PREFIX_DESC));
+ // option to include headers in the response
+ CliOption optAddResponseHeaders = new CliOption("addResponseHeaders", "To include response headers in ImplResponse");
+ optAddResponseHeaders.setType("bool");
+ optAddResponseHeaders.defaultValue(addResponseHeaders.toString());
+ cliOptions.add(optAddResponseHeaders);
+
/*
* Models. You can write model files using the modelTemplateFiles map.
* if you want to create one template for file, you can do so here.
@@ -172,12 +179,19 @@ public class GoServerCodegen extends AbstractGoCodegen {
} else {
additionalProperties.put("serverPort", serverPort);
}
+
if (additionalProperties.containsKey("featureCORS")) {
this.setFeatureCORS(convertPropertyToBooleanAndWriteBack("featureCORS"));
} else {
additionalProperties.put("featureCORS", corsFeatureEnabled);
}
+ if (additionalProperties.containsKey("addResponseHeaders")) {
+ this.setAddResponseHeaders(convertPropertyToBooleanAndWriteBack("addResponseHeaders"));
+ } else {
+ additionalProperties.put("addResponseHeaders", addResponseHeaders);
+ }
+
if (additionalProperties.containsKey(CodegenConstants.ENUM_CLASS_PREFIX)) {
setEnumClassPrefix(Boolean.parseBoolean(additionalProperties.get(CodegenConstants.ENUM_CLASS_PREFIX).toString()));
if (enumClassPrefix) {
@@ -221,10 +235,8 @@ public class GoServerCodegen extends AbstractGoCodegen {
// override imports to only include packages for interface parameters
imports.clear();
- boolean addedOptionalImport = false;
boolean addedTimeImport = false;
boolean addedOSImport = false;
- boolean addedReflectImport = false;
for (CodegenOperation operation : operations) {
for (CodegenParameter param : operation.allParams) {
// import "os" if the operation uses files
@@ -233,7 +245,7 @@ public class GoServerCodegen extends AbstractGoCodegen {
addedOSImport = true;
}
- // import "time" if the operation has a required time parameter.
+ // import "time" if the operation has a required time parameter
if (param.required) {
if (!addedTimeImport && "time.Time".equals(param.dataType)) {
imports.add(createMapping("import", "time"));
@@ -314,4 +326,8 @@ public class GoServerCodegen extends AbstractGoCodegen {
public void setFeatureCORS(Boolean featureCORS) {
this.corsFeatureEnabled = featureCORS;
}
+
+ public void setAddResponseHeaders(Boolean addResponseHeaders) {
+ this.addResponseHeaders = addResponseHeaders;
+ }
}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java
index 17afe550c70..72646d58cd7 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java
@@ -17,6 +17,8 @@
package org.openapitools.codegen.languages;
+import static java.util.Collections.sort;
+
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConstants;
@@ -463,6 +465,8 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/LocalDateAdapter.kt.mustache", infrastructureFolder, "LocalDateAdapter.kt"));
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/LocalDateTimeAdapter.kt.mustache", infrastructureFolder, "LocalDateTimeAdapter.kt"));
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/OffsetDateTimeAdapter.kt.mustache", infrastructureFolder, "OffsetDateTimeAdapter.kt"));
+ supportingFiles.add(new SupportingFile("jvm-common/infrastructure/BigDecimalAdapter.kt.mustache", infrastructureFolder, "BigDecimalAdapter.kt"));
+ supportingFiles.add(new SupportingFile("jvm-common/infrastructure/BigIntegerAdapter.kt.mustache", infrastructureFolder, "BigIntegerAdapter.kt"));
break;
case gson:
@@ -654,6 +658,20 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
operation.path = operation.path.substring(1);
}
+ // sorting operation parameters to make sure path params are parsed before query params
+ if (operation.allParams != null) {
+ sort(operation.allParams, (one, another) -> {
+ if (one.isPathParam && another.isQueryParam) {
+ return -1;
+ }
+ if (one.isQueryParam && another.isPathParam){
+ return 1;
+ }
+
+ return 0;
+ });
+ }
+
// modify the data type of binary form parameters to a more friendly type for multiplatform builds
if (MULTIPLATFORM.equals(getLibrary()) && operation.allParams != null) {
for (CodegenParameter param : operation.allParams) {
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java
index cf3c64b0338..cdaae2afe67 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java
@@ -540,8 +540,10 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
.filter(cm -> Boolean.TRUE.equals(cm.isEnum) && cm.allowableValues != null)
.forEach(cm -> {
cm.imports.add(importMapping.get("JsonValue"));
+ cm.imports.add(importMapping.get("JsonProperty"));
Map item = new HashMap<>();
item.put("import", importMapping.get("JsonValue"));
+ item.put("import", importMapping.get("JsonProperty"));
imports.add(item);
});
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/NimClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/NimClientCodegen.java
index 02e4f1b701c..ff07db2ede8 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/NimClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/NimClientCodegen.java
@@ -31,6 +31,8 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
+import static org.openapitools.codegen.utils.StringUtils.camelize;
+
public class NimClientCodegen extends DefaultCodegen implements CodegenConfig {
final Logger LOGGER = LoggerFactory.getLogger(NimClientCodegen.class);
@@ -297,14 +299,32 @@ public class NimClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toVarName(String name) {
- if (isReservedWord(name)) {
- name = escapeReservedWord(name);
+ // sanitize name
+ name = sanitizeName(name, "\\W-[\\$]"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
+
+ if ("_".equals(name)) {
+ name = "_u";
}
+ // numbers are not allowed at the beginning
if (name.matches("^\\d.*")) {
name = "`" + name + "`";
}
+ // if it's all uppper case, do nothing
+ if (name.matches("^[A-Z0-9_]*$")) {
+ return name;
+ }
+
+ // camelize (lower first character) the variable name
+ // pet_id => petId
+ name = camelize(name, true);
+
+ // for reserved word or word starting with number, append _
+ if (isReservedWord(name)) {
+ name = escapeReservedWord(name);
+ }
+
return name;
}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java
index 9d468195f85..f3324629b45 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java
@@ -416,20 +416,12 @@ public class PhpSymfonyServerCodegen extends AbstractPhpCodegen implements Codeg
if (param.isContainer) {
param.vendorExtensions.put("x-comment-type", param.dataType + "[]");
}
-
- // Quote default values for strings
- // @todo: The default values for headers, forms and query params are handled
- // in DefaultCodegen fromParameter with no real possibility to override
- // the functionality. Thus we are handling quoting of string values here
- if ("string".equals(param.dataType) && param.defaultValue != null && !param.defaultValue.isEmpty()) {
- param.defaultValue = "'" + param.defaultValue + "'";
- }
}
// Create a variable to display the correct return type in comments for interfaces
if (op.returnType != null) {
op.vendorExtensions.put("x-comment-type", op.returnType);
- if (op.returnContainer != null && "array".equals(op.returnContainer)) {
+ if ("array".equals(op.returnContainer)) {
op.vendorExtensions.put("x-comment-type", op.returnType + "[]");
}
} else {
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java
index b38d2448d87..a00683cbd4a 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java
@@ -36,6 +36,8 @@ import org.openapitools.codegen.meta.Stability;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.curiousoddman.rgxgen.RgxGen;
+import com.github.curiousoddman.rgxgen.config.RgxGenOption;
+import com.github.curiousoddman.rgxgen.config.RgxGenProperties;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
@@ -65,10 +67,6 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
// in other code generators, support needs to be enabled on a case-by-case basis.
supportsAdditionalPropertiesWithComposedSchema = true;
- // When the 'additionalProperties' keyword is not present in a OAS schema, allow
- // undeclared properties. This is compliant with the JSON schema specification.
- this.setDisallowAdditionalPropertiesIfNotPresent(false);
-
modifyFeatureSet(features -> features
.includeDocumentationFeatures(DocumentationFeature.Readme)
.wireFormatFeatures(EnumSet.of(WireFormatFeature.JSON, WireFormatFeature.XML, WireFormatFeature.Custom))
@@ -94,9 +92,8 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
ParameterFeature.Cookie
)
);
-
- // this may set datatype right for additional properties
- instantiationTypes.put("map", "dict");
+ // needed for type object with additionalProperties: false
+ typeMapping.put("object", "dict");
languageSpecificPrimitives.add("file_type");
languageSpecificPrimitives.add("none_type");
@@ -111,6 +108,20 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
cliOptions.add(new CliOption(CodegenConstants.PYTHON_ATTR_NONE_IF_UNSET, CodegenConstants.PYTHON_ATTR_NONE_IF_UNSET_DESC)
.defaultValue(Boolean.FALSE.toString()));
+ // option to change how we process + set the data in the 'additionalProperties' keyword.
+ CliOption disallowAdditionalPropertiesIfNotPresentOpt = CliOption.newBoolean(
+ CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT,
+ CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT_DESC).defaultValue(Boolean.FALSE.toString());
+ Map disallowAdditionalPropertiesIfNotPresentOpts = new HashMap<>();
+ disallowAdditionalPropertiesIfNotPresentOpts.put("false",
+ "The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.");
+ disallowAdditionalPropertiesIfNotPresentOpts.put("true",
+ "Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default. NOTE: "+
+ "this option breaks composition and will be removed in 6.0.0"
+ );
+ disallowAdditionalPropertiesIfNotPresentOpt.setEnum(disallowAdditionalPropertiesIfNotPresentOpts);
+ cliOptions.add(disallowAdditionalPropertiesIfNotPresentOpt);
+
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
.stability(Stability.EXPERIMENTAL)
.build();
@@ -160,6 +171,18 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
}
additionalProperties.put("attrNoneIfUnset", attrNoneIfUnset);
+ // When the 'additionalProperties' keyword is not present in a OAS schema, allow
+ // undeclared properties. This is compliant with the JSON schema specification.
+ // setting this to false is required to have composed schemas work because:
+ // anyOf SchemaA + SchemaB, requires that props present only in A are accepted in B because in B
+ // they are additional properties
+ Boolean disallowAddProps = false;
+ if (additionalProperties.containsKey(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT)) {
+ disallowAddProps = Boolean.valueOf(additionalProperties.get(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT).toString());
+ }
+ this.setDisallowAdditionalPropertiesIfNotPresent(disallowAddProps);
+
+
// check library option to ensure only urllib3 is supported
if (!DEFAULT_LIBRARY.equals(getLibrary())) {
throw new RuntimeException("Only the `urllib3` library is supported in the refactored `python` client generator at the moment. Please fall back to `python-legacy` client generator for the time being. We welcome contributions to add back `asyncio`, `tornado` support to the `python` client generator.");
@@ -728,6 +751,62 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
return null;
}
+ @Override
+ protected Schema getAdditionalProperties(Schema schema) {
+ /*
+ Use cases:
+ 1. addProps set to schema in spec: return that schema
+ 2. addProps unset w/ getDisallowAdditionalPropertiesIfNotPresent -> null
+ 3. addProps unset w/ getDisallowAdditionalPropertiesIfNotPresent=False -> new Schema()
+ 4. addProps true -> new Schema() NOTE: v3 only
+ 5. addprops false -> null NOTE: v3 only
+ */
+ Object addProps = schema.getAdditionalProperties();
+ if (addProps instanceof Schema) {
+ return (Schema) addProps;
+ }
+ if (addProps == null) {
+ // When reaching this code path, this should indicate the 'additionalProperties' keyword is
+ // not present in the OAS schema. This is true for OAS 3.0 documents.
+ // However, the parsing logic is broken for OAS 2.0 documents because of the
+ // https://github.com/swagger-api/swagger-parser/issues/1369 issue.
+ // When OAS 2.0 documents are parsed, the swagger-v2-converter ignores the 'additionalProperties'
+ // keyword if the value is boolean. That means codegen is unable to determine whether
+ // additional properties are allowed or not.
+ //
+ // The original behavior was to assume additionalProperties had been set to false.
+ if (getDisallowAdditionalPropertiesIfNotPresent()) {
+ // If the 'additionalProperties' keyword is not present in a OAS schema,
+ // interpret as if the 'additionalProperties' keyword had been set to false.
+ // This is NOT compliant with the JSON schema specification. It is the original
+ // 'openapi-generator' behavior.
+ return null;
+ }
+ /*
+ // The disallowAdditionalPropertiesIfNotPresent CLI option has been set to true,
+ // but for now that only works with OAS 3.0 documents.
+ // The new behavior does not work with OAS 2.0 documents.
+ if (extensions == null || !extensions.containsKey(EXTENSION_OPENAPI_DOC_VERSION)) {
+ // Fallback to the legacy behavior.
+ return null;
+ }
+ // Get original swagger version from OAS extension.
+ // Note openAPI.getOpenapi() is always set to 3.x even when the document
+ // is converted from a OAS/Swagger 2.0 document.
+ // https://github.com/swagger-api/swagger-parser/pull/1374
+ SemVer version = new SemVer((String)extensions.get(EXTENSION_OPENAPI_DOC_VERSION));
+ if (version.major != 3) {
+ return null;
+ }
+ */
+ }
+ if (addProps == null || (addProps instanceof Boolean && (Boolean) addProps)) {
+ // Return empty schema to allow any type
+ return new Schema();
+ }
+ return null;
+ }
+
/**
* Return a string representation of the Python types for the specified OAS schema.
* Primitive types in the OAS specification are implemented in Python using the corresponding
@@ -767,16 +846,39 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
}
}
if (isAnyTypeSchema(p)) {
+ // for v2 specs only, swagger-parser never generates an AnyType schemas even though it should generate them
+ // https://github.com/swagger-api/swagger-parser/issues/1378
+ // switch to v3 if you need AnyType to work
return prefix + "bool, date, datetime, dict, float, int, list, str, none_type" + suffix;
}
+ String originalSpecVersion = "X";
+ if (this.openAPI.getExtensions() != null && this.openAPI.getExtensions().containsKey("x-original-swagger-version")) {
+ originalSpecVersion = (String) this.openAPI.getExtensions().get("x-original-swagger-version");
+ originalSpecVersion = originalSpecVersion.substring(0, 1);
+
+ }
+ Boolean v2DisallowAdditionalPropertiesIfNotPresentAddPropsNullCase = (getAdditionalProperties(p) == null && this.getDisallowAdditionalPropertiesIfNotPresent() && originalSpecVersion.equals("2"));
+ Schema emptySchema = new Schema();
+ Boolean v2WithCompositionAddPropsAnyTypeSchemaCase = (getAdditionalProperties(p) != null && emptySchema.equals(getAdditionalProperties(p)) && originalSpecVersion.equals("2"));
+ if (isFreeFormObject(p) && (v2DisallowAdditionalPropertiesIfNotPresentAddPropsNullCase || v2WithCompositionAddPropsAnyTypeSchemaCase)) {
+ // for v2 specs only, input AnyType schemas (type unset) or schema {} results in FreeFromObject schemas
+ // per https://github.com/swagger-api/swagger-parser/issues/1378
+ // v2 spec uses cases
+ // 1. AnyType schemas
+ // 2. type object schema with no other info
+ // use case 1 + 2 -> both become use case 1
+ // switch to v3 if you need use cases 1 + 2 to work correctly
+ return prefix + "bool, date, datetime, dict, float, int, list, str, none_type" + fullSuffix;
+ }
// Resolve $ref because ModelUtils.isXYZ methods do not automatically resolve references.
if (ModelUtils.isNullable(ModelUtils.getReferencedSchema(this.openAPI, p))) {
fullSuffix = ", none_type" + suffix;
}
- if (isFreeFormObject(p) && getAdditionalProperties(p) == null) {
- return prefix + "bool, date, datetime, dict, float, int, list, str" + fullSuffix;
- }
- if ((ModelUtils.isMapSchema(p) || "object".equals(p.getType())) && getAdditionalProperties(p) != null) {
+ Boolean v3WithCompositionAddPropsAnyTypeSchemaCase = (getAdditionalProperties(p) != null && emptySchema.equals(getAdditionalProperties(p)) && originalSpecVersion.equals("3"));
+ if (isFreeFormObject(p) && v3WithCompositionAddPropsAnyTypeSchemaCase) {
+ // v3 code path, use case: type object schema with no other schema info
+ return prefix + "{str: (bool, date, datetime, dict, float, int, list, str, none_type)}" + fullSuffix;
+ } else if ((ModelUtils.isMapSchema(p) || "object".equals(p.getType())) && getAdditionalProperties(p) != null) {
Schema inner = getAdditionalProperties(p);
return prefix + "{str: " + getTypeString(inner, "(", ")", referencedModelNames) + "}" + fullSuffix;
} else if (ModelUtils.isArraySchema(p)) {
@@ -835,7 +937,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
// The 'addProps' may be a reference, getTypeDeclaration will resolve
// the reference.
List referencedModelNames = new ArrayList();
- codegenModel.additionalPropertiesType = getTypeString(addProps, "", "", referencedModelNames);
+ getTypeString(addProps, "", "", referencedModelNames);
if (referencedModelNames.size() != 0) {
// Models that are referenced in the 'additionalPropertiesType' keyword
// must be added to the imports.
@@ -894,6 +996,13 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
return "\"" + in + "\"";
}
+ @Override
+ public String toExampleValue(Schema schema) {
+ Object objExample = getObjectExample(schema);
+ String modelName = getModelName(schema);
+ return toExampleValueRecursive(modelName, schema, objExample, 1, "", 0, Sets.newHashSet());
+ }
+
public String toExampleValue(Schema schema, Object objExample) {
String modelName = getModelName(schema);
return toExampleValueRecursive(modelName, schema, objExample, 1, "", 0, Sets.newHashSet());
@@ -974,7 +1083,7 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
// checks if the current schema has already been passed in. If so, breaks the current recursive pass
if (seenSchemas.contains(schema)) {
if (modelName != null) {
- return fullPrefix + modelName + closeChars;
+ return fullPrefix + closeChars;
} else {
// this is a recursive schema
// need to add a reasonable example to avoid
@@ -1050,18 +1159,39 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
return fullPrefix + example + closeChars;
} else if (StringUtils.isNotBlank(schema.getPattern())) {
String pattern = schema.getPattern();
- RgxGen rgxGen = new RgxGen(pattern);
+ /*
+ RxGen does not support our ECMA dialect https://github.com/curious-odd-man/RgxGen/issues/56
+ So strip off the leading / and trailing / and turn on ignore case if we have it
+ */
+ Pattern valueExtractor = Pattern.compile("^/?(.+?)/?(.?)$");
+ Matcher m = valueExtractor.matcher(pattern);
+ RgxGen rgxGen = null;
+ if (m.find()) {
+ int groupCount = m.groupCount();
+ if (groupCount == 1) {
+ // only pattern found
+ String isolatedPattern = m.group(1);
+ rgxGen = new RgxGen(isolatedPattern);
+ } else if (groupCount == 2) {
+ // patterns and flag found
+ String isolatedPattern = m.group(1);
+ String flags = m.group(2);
+ if (flags.contains("i")) {
+ rgxGen = new RgxGen(isolatedPattern);
+ RgxGenProperties properties = new RgxGenProperties();
+ RgxGenOption.CASE_INSENSITIVE.setInProperties(properties, true);
+ rgxGen.setProperties(properties);
+ } else {
+ rgxGen = new RgxGen(isolatedPattern);
+ }
+ }
+ } else {
+ rgxGen = new RgxGen(pattern);
+ }
+
// this seed makes it so if we have [a-z] we pick a
Random random = new Random(18);
- String sample = rgxGen.generate(random);
- // omit leading / and trailing /, omit trailing /i
- Pattern valueExtractor = Pattern.compile("^/?(.+?)/?.?$");
- Matcher m = valueExtractor.matcher(sample);
- if (m.find()) {
- example = m.group(m.groupCount());
- } else {
- example = "";
- }
+ example = rgxGen.generate(random);
} else if (schema.getMinLength() != null) {
example = "";
int len = schema.getMinLength().intValue();
@@ -1099,8 +1229,9 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
// If the example is already a list, return it directly instead of wrongly wrap it in another list
return fullPrefix + objExample.toString() + closeChars;
}
- seenSchemas.add(schema);
- example = fullPrefix + "[" + "\n" + toExampleValueRecursive(itemModelName, itemSchema, objExample, indentationLevel + 1, "", exampleLine + 1, seenSchemas) + ",\n" + closingIndentation + "]" + closeChars;
+ Set newSeenSchemas = new HashSet<>(seenSchemas);
+ newSeenSchemas.add(schema);
+ example = fullPrefix + "[" + "\n" + toExampleValueRecursive(itemModelName, itemSchema, objExample, indentationLevel + 1, "", exampleLine + 1, newSeenSchemas) + ",\n" + closingIndentation + "]" + closeChars;
return example;
} else if (ModelUtils.isMapSchema(schema)) {
if (modelName == null) {
@@ -1122,8 +1253,9 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
addPropPrefix = ensureQuotes(key) + ": ";
}
String addPropsModelName = getModelName(addPropsSchema);
- seenSchemas.add(schema);
- example = fullPrefix + "\n" + toExampleValueRecursive(addPropsModelName, addPropsSchema, addPropsExample, indentationLevel + 1, addPropPrefix, exampleLine + 1, seenSchemas) + ",\n" + closingIndentation + closeChars;
+ Set newSeenSchemas = new HashSet<>(seenSchemas);
+ newSeenSchemas.add(schema);
+ example = fullPrefix + "\n" + toExampleValueRecursive(addPropsModelName, addPropsSchema, addPropsExample, indentationLevel + 1, addPropPrefix, exampleLine + 1, newSeenSchemas) + ",\n" + closingIndentation + closeChars;
} else {
example = fullPrefix + closeChars;
}
@@ -1146,11 +1278,9 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
return fullPrefix + closeChars;
}
}
- // Adds schema to seenSchemas before running example model function. romoves schema after running
- // the function. It also doesnt keep track of any schemas within the ObjectModel.
- seenSchemas.add(schema);
- String exampleForObjectModel = exampleForObjectModel(schema, fullPrefix, closeChars, null, indentationLevel, exampleLine, closingIndentation, seenSchemas);
- seenSchemas.remove(schema);
+ Set newSeenSchemas = new HashSet<>(seenSchemas);
+ newSeenSchemas.add(schema);
+ String exampleForObjectModel = exampleForObjectModel(schema, fullPrefix, closeChars, null, indentationLevel, exampleLine, closingIndentation, newSeenSchemas);
return exampleForObjectModel;
} else if (ModelUtils.isComposedSchema(schema)) {
// TODO add examples for composed schema models without discriminators
@@ -1167,9 +1297,9 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
cp.setExample(discPropNameValue);
// Adds schema to seenSchemas before running example model function. romoves schema after running
// the function. It also doesnt keep track of any schemas within the ObjectModel.
- seenSchemas.add(modelSchema);
- String exampleForObjectModel = exampleForObjectModel(modelSchema, fullPrefix, closeChars, cp, indentationLevel, exampleLine, closingIndentation, seenSchemas);
- seenSchemas.remove(modelSchema);
+ Set newSeenSchemas = new HashSet<>(seenSchemas);
+ newSeenSchemas.add(schema);
+ String exampleForObjectModel = exampleForObjectModel(modelSchema, fullPrefix, closeChars, cp, indentationLevel, exampleLine, closingIndentation, newSeenSchemas);
return exampleForObjectModel;
} else {
return fullPrefix + closeChars;
@@ -1193,6 +1323,23 @@ public class PythonClientCodegen extends PythonLegacyClientCodegen {
for (Map.Entry entry : requiredAndOptionalProps.entrySet()) {
String propName = entry.getKey();
Schema propSchema = entry.getValue();
+ boolean readOnly = false;
+ if (propSchema.getReadOnly() != null) {
+ readOnly = propSchema.getReadOnly();
+ }
+ if (readOnly) {
+ continue;
+ }
+ String ref = propSchema.get$ref();
+ if (ref != null) {
+ Schema refSchema = ModelUtils.getSchema(this.openAPI, ModelUtils.getSimpleRef(ref));
+ if (refSchema.getReadOnly() != null) {
+ readOnly = refSchema.getReadOnly();
+ }
+ if (readOnly) {
+ continue;
+ }
+ }
propName = toVarName(propName);
String propModelName = null;
Object propExample = null;
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonLegacyClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonLegacyClientCodegen.java
index 7d5cc631a8b..138b1c54356 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonLegacyClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonLegacyClientCodegen.java
@@ -17,6 +17,7 @@
package org.openapitools.codegen.languages;
+import io.swagger.v3.oas.models.media.Schema;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.meta.features.*;
@@ -35,6 +36,7 @@ public class PythonLegacyClientCodegen extends AbstractPythonCodegen implements
// nose is a python testing framework, we use pytest if USE_NOSE is unset
public static final String USE_NOSE = "useNose";
public static final String RECURSION_LIMIT = "recursionLimit";
+ public static final String PYTHON_ATTR_NONE_IF_UNSET = "pythonAttrNoneIfUnset";
protected String packageUrl;
protected String apiDocPath = "docs/";
@@ -430,5 +432,4 @@ public class PythonLegacyClientCodegen extends AbstractPythonCodegen implements
public String generatePackageName(String packageName) {
return underscore(packageName.replaceAll("[^\\w]+", ""));
}
-
}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubyClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubyClientCodegen.java
index 40b2d9c22ee..96a5f5d7c3f 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubyClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubyClientCodegen.java
@@ -748,8 +748,14 @@ public class RubyClientCodegen extends AbstractRubyCodegen {
return moduleName + "::" + codegenModel.classname + "::" + enumVars.get(0).get("name");
} else if (codegenModel.oneOf != null && !codegenModel.oneOf.isEmpty()) {
String subModel = (String) codegenModel.oneOf.toArray()[0];
- String oneOf = constructExampleCode(modelMaps.get(subModel), modelMaps, processedModelMap);
- return oneOf;
+ if (modelMaps.containsKey(subModel)) {
+ // oneOf models
+ return constructExampleCode(modelMaps.get(subModel), modelMaps, processedModelMap);
+ } else {
+ // TODO oneOf primitive type not supported at the moment
+ LOGGER.warn("oneOf example value not supported at the moment.");
+ return "nil";
+ }
} else {
processedModelMap.put(model, 1);
}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubySinatraServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubySinatraServerCodegen.java
index 12f8f9a2a70..c81426eb017 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubySinatraServerCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RubySinatraServerCodegen.java
@@ -87,6 +87,7 @@ public class RubySinatraServerCodegen extends AbstractRubyCodegen {
supportingFiles.add(new SupportingFile("Gemfile", "", "Gemfile"));
supportingFiles.add(new SupportingFile("README.md", "", "README.md"));
supportingFiles.add(new SupportingFile("openapi.mustache", "", "openapi.yaml"));
+ supportingFiles.add(new SupportingFile("Dockerfile", "", "Dockerfile"));
}
@Override
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java
index 5ff03773da1..a47e86573fb 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java
@@ -1560,12 +1560,12 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig {
LOGGER.trace("Post processing model: {}", cm);
- if (cm.dataType != null && "object".equals(cm.dataType)) {
+ if ("object".equals(cm.dataType)) {
// Object isn't a sensible default. Instead, we set it to
// 'null'. This ensures that we treat this model as a struct
// with multiple parameters.
cm.dataType = null;
- } else if (cm.dataType != null && "map".equals(cm.dataType)) {
+ } else if ("map".equals(cm.dataType)) {
if (!cm.allVars.isEmpty() || cm.additionalPropertiesType == null) {
// We don't yet support `additionalProperties` that also have
// properties. If we see variables, we ignore the
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java
index 058acbed956..4c4f0e19496 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java
@@ -336,8 +336,8 @@ public class SpringCodegen extends AbstractJavaCodegen
}
additionalProperties.put(UNHANDLED_EXCEPTION_HANDLING, this.isUnhandledException());
- typeMapping.put("file", "org.springframework.core.io.Resource");
- importMapping.put("org.springframework.core.io.Resource", "org.springframework.core.io.Resource");
+ typeMapping.put("file", "org.springframework.web.multipart.MultipartFile");
+ importMapping.put("org.springframework.web.multipart.MultipartFile", "org.springframework.web.multipart.MultipartFile");
if (useOptional) {
writePropertyBack(USE_OPTIONAL, useOptional);
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift4Codegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift4Codegen.java
index e5724a3c7e8..0133cfb3c17 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift4Codegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift4Codegen.java
@@ -534,12 +534,12 @@ public class Swift4Codegen extends DefaultCodegen implements CodegenConfig {
@Override
public boolean isDataTypeFile(String dataType) {
- return dataType != null && "URL".equals(dataType);
+ return "URL".equals(dataType);
}
@Override
public boolean isDataTypeBinary(final String dataType) {
- return dataType != null && "Data".equals(dataType);
+ return "Data".equals(dataType);
}
/**
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift5ClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift5ClientCodegen.java
index a5d71b4d302..5d7f86a40d3 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift5ClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift5ClientCodegen.java
@@ -61,6 +61,9 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
public static final String SWIFT_USE_API_NAMESPACE = "swiftUseApiNamespace";
public static final String DEFAULT_POD_AUTHORS = "OpenAPI Generator";
public static final String LENIENT_TYPE_CAST = "lenientTypeCast";
+ public static final String USE_SPM_FILE_STRUCTURE = "useSPMFileStructure";
+ public static final String SWIFT_PACKAGE_PATH = "swiftPackagePath";
+ public static final String USE_BACKTICK_ESCAPES = "useBacktickEscapes";
protected static final String LIBRARY_ALAMOFIRE = "alamofire";
protected static final String LIBRARY_URLSESSION = "urlsession";
protected static final String RESPONSE_LIBRARY_PROMISE_KIT = "PromiseKit";
@@ -73,9 +76,12 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
protected boolean objcCompatible = false;
protected boolean lenientTypeCast = false;
protected boolean readonlyProperties = false;
- protected boolean swiftUseApiNamespace;
+ protected boolean swiftUseApiNamespace = false;
+ protected boolean useSPMFileStructure = false;
+ protected String swiftPackagePath = "Classes" + File.separator + "OpenAPIs";
+ protected boolean useBacktickEscapes = false;
protected String[] responseAs = new String[0];
- protected String sourceFolder = "Classes" + File.separator + "OpenAPIs";
+ protected String sourceFolder = swiftPackagePath;
protected HashSet objcReservedWords;
protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/";
@@ -197,7 +203,6 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping = new HashMap<>();
typeMapping.put("array", "Array");
- typeMapping.put("List", "Array");
typeMapping.put("map", "Dictionary");
typeMapping.put("set", "Set");
typeMapping.put("date", "Date");
@@ -220,8 +225,8 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("UUID", "UUID");
typeMapping.put("URI", "String");
typeMapping.put("decimal", "Decimal");
- typeMapping.put("object", "Any");
- typeMapping.put("AnyType", "Any");
+ typeMapping.put("object", "AnyCodable");
+ typeMapping.put("AnyType", "AnyCodable");
importMapping = new HashMap<>();
@@ -259,8 +264,15 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
"Accept and cast values for simple types (string->bool, "
+ "string->int, int->string)")
.defaultValue(Boolean.FALSE.toString()));
+ cliOptions.add(new CliOption(USE_BACKTICK_ESCAPES,
+ "Escape reserved words using backticks (default: false)")
+ .defaultValue(Boolean.FALSE.toString()));
cliOptions.add(new CliOption(CodegenConstants.API_NAME_PREFIX, CodegenConstants.API_NAME_PREFIX_DESC));
+ cliOptions.add(new CliOption(USE_SPM_FILE_STRUCTURE, "Use SPM file structure"
+ + " and set the source path to Sources" + File.separator + "{{projectName}} (default: false)."));
+ cliOptions.add(new CliOption(SWIFT_PACKAGE_PATH, "Set a custom source path instead of "
+ + projectName + File.separator + "Classes" + File.separator + "OpenAPIs" + "."));
supportedLibraries.put(LIBRARY_URLSESSION, "[DEFAULT] HTTP client: URLSession");
supportedLibraries.put(LIBRARY_ALAMOFIRE, "HTTP client: Alamofire");
@@ -334,7 +346,15 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
final Schema additionalProperties = getAdditionalProperties(schema);
if (additionalProperties != null) {
- codegenModel.additionalPropertiesType = getSchemaType(additionalProperties);
+ Schema inner = null;
+ if (ModelUtils.isArraySchema(schema)) {
+ ArraySchema ap = (ArraySchema) schema;
+ inner = ap.getItems();
+ } else if (ModelUtils.isMapSchema(schema)) {
+ inner = getAdditionalProperties(schema);
+ }
+
+ codegenModel.additionalPropertiesType = inner != null ? getTypeDeclaration(inner) : getSchemaType(additionalProperties);
}
}
@@ -414,6 +434,20 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
additionalProperties.put(POD_AUTHORS, DEFAULT_POD_AUTHORS);
}
+ if (additionalProperties.containsKey(USE_SPM_FILE_STRUCTURE)) {
+ setUseSPMFileStructure(convertPropertyToBooleanAndWriteBack(USE_SPM_FILE_STRUCTURE));
+ sourceFolder = "Sources" + File.separator + projectName;
+ }
+
+ if (additionalProperties.containsKey(SWIFT_PACKAGE_PATH) && ((String)additionalProperties.get(SWIFT_PACKAGE_PATH)).length() > 0) {
+ setSwiftPackagePath((String)additionalProperties.get(SWIFT_PACKAGE_PATH));
+ sourceFolder = swiftPackagePath;
+ }
+
+ if (additionalProperties.containsKey(USE_BACKTICK_ESCAPES)) {
+ setUseBacktickEscapes(convertPropertyToBooleanAndWriteBack(USE_BACKTICK_ESCAPES));
+ }
+
setLenientTypeCast(convertPropertyToBooleanAndWriteBack(LENIENT_TYPE_CAST));
// make api and model doc path available in mustache template
@@ -501,7 +535,7 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
if (this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
- return "_" + name; // add an underscore to the name
+ return useBacktickEscapes && !objcCompatible ? "`" + name + "`" : "_" + name;
}
@Override
@@ -546,12 +580,12 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
@Override
public boolean isDataTypeFile(String dataType) {
- return dataType != null && "URL".equals(dataType);
+ return "URL".equals(dataType);
}
@Override
public boolean isDataTypeBinary(final String dataType) {
- return dataType != null && "Data".equals(dataType);
+ return "Data".equals(dataType);
}
/**
@@ -720,11 +754,16 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
// pet_id => petId
name = camelize(name, true);
- // for reserved word or word starting with number, append _
- if (isReservedWord(name) || name.matches("^\\d.*")) {
+ // for reserved words surround with `` or append _
+ if (isReservedWord(name)) {
name = escapeReservedWord(name);
}
+ // for words starting with number, append _
+ if (name.matches("^\\d.*")) {
+ name = "_" + name;
+ }
+
return name;
}
@@ -745,11 +784,16 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
// pet_id => petId
name = camelize(name, true);
- // for reserved word or word starting with number, append _
- if (isReservedWord(name) || name.matches("^\\d.*")) {
+ // for reserved words surround with ``
+ if (isReservedWord(name)) {
name = escapeReservedWord(name);
}
+ // for words starting with number, append _
+ if (name.matches("^\\d.*")) {
+ name = "_" + name;
+ }
+
return name;
}
@@ -806,6 +850,18 @@ public class Swift5ClientCodegen extends DefaultCodegen implements CodegenConfig
this.swiftUseApiNamespace = swiftUseApiNamespace;
}
+ public void setUseSPMFileStructure(boolean useSPMFileStructure) {
+ this.useSPMFileStructure = useSPMFileStructure;
+ }
+
+ public void setSwiftPackagePath(String swiftPackagePath) {
+ this.swiftPackagePath = swiftPackagePath;
+ }
+
+ public void setUseBacktickEscapes(boolean useBacktickEscapes) {
+ this.useBacktickEscapes = useBacktickEscapes;
+ }
+
@Override
public String toEnumValue(String value, String datatype) {
// for string, array of string
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java
index 77bf353a41a..e91ddecda38 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java
@@ -384,7 +384,7 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
@Override
public boolean isDataTypeFile(final String dataType) {
- return dataType != null && "Blob".equals(dataType);
+ return "Blob".equals(dataType);
}
@Override
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptInversifyClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptInversifyClientCodegen.java
index 4b3daba3f85..6de4f086413 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptInversifyClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptInversifyClientCodegen.java
@@ -141,7 +141,7 @@ public class TypeScriptInversifyClientCodegen extends AbstractTypeScriptClientCo
@Override
public boolean isDataTypeFile(final String dataType) {
- return dataType != null && "Blob".equals(dataType);
+ return "Blob".equals(dataType);
}
@Override
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNestjsClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNestjsClientCodegen.java
index 4e5e6c903ce..771e66db0a4 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNestjsClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNestjsClientCodegen.java
@@ -216,7 +216,7 @@ public class TypeScriptNestjsClientCodegen extends AbstractTypeScriptClientCodeg
@Override
public boolean isDataTypeFile(final String dataType) {
- return dataType != null && "Blob".equals(dataType);
+ return "Blob".equals(dataType);
}
@Override
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java
index 9ff6f444c57..613b9da70f2 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java
@@ -82,7 +82,7 @@ public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen
@Override
public boolean isDataTypeFile(final String dataType) {
- return dataType != null && "RequestFile".equals(dataType);
+ return "RequestFile".equals(dataType);
}
@Override
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java
index a2f79f519ad..bdecf7febe1 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java
@@ -98,7 +98,7 @@ public class TypeScriptRxjsClientCodegen extends AbstractTypeScriptClientCodegen
@Override
public boolean isDataTypeFile(final String dataType) {
- return dataType != null && "Blob".equals(dataType);
+ return "Blob".equals(dataType);
}
@Override
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/jersey2/AbstractOpenApiSchema.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/jersey2/AbstractOpenApiSchema.mustache
index 6eb87a90b9b..734ef553e30 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/jersey2/AbstractOpenApiSchema.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/jersey2/AbstractOpenApiSchema.mustache
@@ -1,6 +1,6 @@
{{>licenseInfo}}
-package {{invokerPackage}}.model;
+package {{modelPackage}};
import {{invokerPackage}}.ApiException;
import java.util.Objects;
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/native/ApiClient.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/native/ApiClient.mustache
index 4c915fb3f38..ea46db7331d 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/native/ApiClient.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/native/ApiClient.mustache
@@ -16,7 +16,6 @@ import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
-import java.nio.charset.Charset;
import java.time.Duration;
{{#java8}}
import java.time.OffsetDateTime;
@@ -29,6 +28,8 @@ import java.util.StringJoiner;
import java.util.function.Consumer;
import java.util.stream.Collectors;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
/**
* Configuration and utility class for API clients.
*
@@ -45,8 +46,6 @@ import java.util.stream.Collectors;
{{>generatedAnnotation}}
public class ApiClient {
- private static final Charset UTF_8 = Charset.forName("UTF-8");
-
private HttpClient.Builder builder;
private ObjectMapper mapper;
private String scheme;
@@ -171,7 +170,7 @@ public class ApiClient {
public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) {
this.builder = builder;
this.mapper = mapper;
- updateBaseUri(baseUri);
+ updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri());
interceptor = null;
readTimeout = null;
responseInterceptor = null;
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/native/api.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/native/api.mustache
index 2adef3a6b0e..e91e72f97b9 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/native/api.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/native/api.mustache
@@ -65,6 +65,14 @@ public class {{classname}} {
}
{{/asyncNative}}
+ protected ApiException createApiException(HttpResponse response, String msgPrefix) throws IOException {
+ String body = response.body() == null ? null : new String(response.body().readAllBytes());
+ if (body != null) {
+ msgPrefix += ": " + body;
+ }
+ return new ApiException(response.statusCode(), msgPrefix, response.headers(), body);
+ }
+
{{#operation}}
{{#vendorExtensions.x-group-parameters}}
{{#hasParams}}
@@ -207,10 +215,7 @@ public class {{classname}} {
memberVarResponseInterceptor.accept(localVarResponse);
}
if (localVarResponse.statusCode()/ 100 != 2) {
- throw new ApiException(localVarResponse.statusCode(),
- "{{operationId}} call received non-success response",
- localVarResponse.headers(),
- localVarResponse.body() == null ? null : new String(localVarResponse.body().readAllBytes()));
+ throw createApiException(localVarResponse, "{{operationId}} call received non-success response");
}
return new ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>(
localVarResponse.statusCode(),
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/build.gradle.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/build.gradle.mustache
index c027064edd4..7e3d97298ea 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/build.gradle.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/build.gradle.mustache
@@ -40,14 +40,8 @@ if(hasProperty('target') && target == 'android') {
targetSdkVersion 25
}
compileOptions {
- {{#java8}}
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
- {{/java8}}
- {{^java8}}
- sourceCompatibility JavaVersion.VERSION_1_7
- targetCompatibility JavaVersion.VERSION_1_7
- {{/java8}}
}
// Rename the aar correctly
@@ -92,14 +86,8 @@ if(hasProperty('target') && target == 'android') {
apply plugin: 'java'
apply plugin: 'maven'
- {{#java8}}
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
- {{/java8}}
- {{^java8}}
- sourceCompatibility = JavaVersion.VERSION_1_7
- targetCompatibility = JavaVersion.VERSION_1_7
- {{/java8}}
install {
repositories.mavenInstaller {
@@ -116,8 +104,8 @@ if(hasProperty('target') && target == 'android') {
dependencies {
implementation 'io.swagger:swagger-annotations:1.5.24'
implementation "com.google.code.findbugs:jsr305:3.0.2"
- implementation 'com.squareup.okhttp3:okhttp:3.14.7'
- implementation 'com.squareup.okhttp3:logging-interceptor:3.14.7'
+ implementation 'com.squareup.okhttp3:okhttp:4.9.1'
+ implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'io.gsonfire:gson-fire:1.8.4'
{{#hasOAuthMethods}}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api.mustache
index 006e6cf8f93..dce5d647267 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api.mustache
@@ -71,7 +71,7 @@ public class {{classname}} {
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
- public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException {
+ public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.web.multipart.MultipartFile{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException {
{{#returnType}}
return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).getBody();
{{/returnType}}
@@ -99,7 +99,7 @@ public class {{classname}} {
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
- public ResponseEntity<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException {
+ public ResponseEntity<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.web.multipart.MultipartFile{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException {
Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
{{#allParams}}{{#required}}
// verify the required parameter '{{paramName}}' is set
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api_test.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api_test.mustache
index 119194543c3..56d89a842d4 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api_test.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api_test.mustache
@@ -34,7 +34,7 @@ public class {{classname}}Test {
@Test
public void {{operationId}}Test() {
{{#allParams}}
- {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}} = null;
+ {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.web.multipart.MultipartFile{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}} = null;
{{/allParams}}
{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
diff --git a/modules/openapi-generator/src/main/resources/JavaJaxRS/pojo.mustache b/modules/openapi-generator/src/main/resources/JavaJaxRS/pojo.mustache
index 6bde84c3fdd..637add30c23 100644
--- a/modules/openapi-generator/src/main/resources/JavaJaxRS/pojo.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaJaxRS/pojo.mustache
@@ -87,7 +87,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {{#seriali
{{{vendorExtensions.x-extra-annotation}}}
{{/vendorExtensions.x-extra-annotation}}
{{#jackson}}
- @JsonProperty("{{baseName}}")
+ @JsonProperty(value = "{{baseName}}"{{#isReadOnly}}, access = JsonProperty.Access.READ_ONLY{{/isReadOnly}}{{#isWriteOnly}}, access = JsonProperty.Access.WRITE_ONLY{{/isWriteOnly}})
{{/jackson}}
@ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}}
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/homeController.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/homeController.mustache
index f909a15b37d..2b244c540bc 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/homeController.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/homeController.mustache
@@ -4,7 +4,7 @@ package {{configPackage}};
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
-import org.springframework.core.io.Resource;
+import org.springframework.web.multipart.MultipartFile;
{{/useSpringfox}}
import org.springframework.stereotype.Controller;
{{^useSpringfox}}
diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
index 886c41c7f4e..87ab2b5e352 100644
--- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
+++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
@@ -131,3 +131,4 @@ org.openapitools.codegen.languages.TypeScriptNestjsClientCodegen
org.openapitools.codegen.languages.TypeScriptNodeClientCodegen
org.openapitools.codegen.languages.TypeScriptReduxQueryClientCodegen
org.openapitools.codegen.languages.TypeScriptRxjsClientCodegen
+org.openapitools.codegen.languages.GoEchoServerCodegen
diff --git a/modules/openapi-generator/src/main/resources/bash/Dockerfile.mustache b/modules/openapi-generator/src/main/resources/bash/Dockerfile.mustache
index b59e5a3665a..d5d8a907a31 100644
--- a/modules/openapi-generator/src/main/resources/bash/Dockerfile.mustache
+++ b/modules/openapi-generator/src/main/resources/bash/Dockerfile.mustache
@@ -1,7 +1,6 @@
-FROM ubuntu:16.10
+FROM alpine:3.12.0
-RUN apt-get update -y && apt-get full-upgrade -y
-RUN apt-get install -y bash-completion zsh curl cowsay git vim bsdmainutils
+RUN apk add --update --no-cache curl ca-certificates bash bash-completion zsh curl git vim ncurses util-linux
ADD {{scriptName}} /usr/bin/{{scriptName}}
ADD _{{scriptName}} /usr/local/share/zsh/site-functions/_{{scriptName}}
@@ -30,7 +29,7 @@ RUN echo 'export PROMPT="[{{appName}}] \$ "' >> ~/.zshrc
#
# Setup a welcome message with basic instruction
#
-RUN echo 'cat << EOF\n\
+RUN echo -e 'echo "\
\n\
This Docker provides preconfigured environment for running the command\n\
line REST client for $(tput setaf 6){{appName}}$(tput sgr0).\n\
@@ -63,7 +62,14 @@ $ {{scriptName}} -h\n\
By default you are logged into Zsh with full autocompletion for your REST API,\n\
but you can switch to Bash, where basic autocompletion is also supported.\n\
\n\
-EOF\n\
+"\
' | tee -a ~/.bashrc ~/.zshrc
-ENTRYPOINT ["zsh"]
+#
+# Poormans chsh & cleanup to make image as compact as possible
+#
+
+RUN sed -i 's/root:x:0:0:root:\/root:\/bin\/ash/root:x:0:0:root:\/root:\/bin\/zsh/' /etc/passwd
+RUN apk del git vim && rm -f /var/cache/apk/*
+
+ENTRYPOINT ["/bin/zsh"]
diff --git a/modules/openapi-generator/src/main/resources/cpp-qt5-client/helpers-body.mustache b/modules/openapi-generator/src/main/resources/cpp-qt5-client/helpers-body.mustache
index a4c04a8951c..0661117b0ab 100644
--- a/modules/openapi-generator/src/main/resources/cpp-qt5-client/helpers-body.mustache
+++ b/modules/openapi-generator/src/main/resources/cpp-qt5-client/helpers-body.mustache
@@ -9,47 +9,83 @@ namespace {{this}} {
class {{prefix}}SerializerSettings {
public:
- static void setDateTimeFormat(const QString & dtFormat){
- getInstance()->dateTimeFormat = dtFormat;
+ struct CustomDateTimeFormat{
+ bool isStringSet = false;
+ QString formatString;
+ bool isEnumSet = false;
+ Qt::DateFormat formatEnum;
+ };
+
+ static CustomDateTimeFormat getCustomDateTimeFormat() {
+ return getInstance()->customDateTimeFormat;
}
- static QString getDateTimeFormat() {
- return getInstance()->dateTimeFormat;
+
+ static void setDateTimeFormatString(const QString &dtFormat){
+ getInstance()->customDateTimeFormat.isStringSet = true;
+ getInstance()->customDateTimeFormat.isEnumSet = false;
+ getInstance()->customDateTimeFormat.formatString = dtFormat;
}
+
+ static void setDateTimeFormatEnum(const Qt::DateFormat &dtFormat){
+ getInstance()->customDateTimeFormat.isEnumSet = true;
+ getInstance()->customDateTimeFormat.isStringSet = false;
+ getInstance()->customDateTimeFormat.formatEnum = dtFormat;
+ }
+
static {{prefix}}SerializerSettings *getInstance(){
if(instance == nullptr){
instance = new {{prefix}}SerializerSettings();
}
return instance;
}
+
private:
explicit {{prefix}}SerializerSettings(){
instance = this;
- dateTimeFormat.clear();
+ customDateTimeFormat.isStringSet = false;
+ customDateTimeFormat.isEnumSet = false;
}
static {{prefix}}SerializerSettings *instance;
- QString dateTimeFormat;
+ CustomDateTimeFormat customDateTimeFormat;
};
{{prefix}}SerializerSettings * {{prefix}}SerializerSettings::instance = nullptr;
-bool setDateTimeFormat(const QString& dateTimeFormat){
+bool setDateTimeFormat(const QString &dateTimeFormat){
bool success = false;
auto dt = QDateTime::fromString(QDateTime::currentDateTime().toString(dateTimeFormat), dateTimeFormat);
- if(dt.isValid()){
+ if (dt.isValid()) {
success = true;
- {{prefix}}SerializerSettings::setDateTimeFormat(dateTimeFormat);
+ {{prefix}}SerializerSettings::setDateTimeFormatString(dateTimeFormat);
}
return success;
}
+bool setDateTimeFormat(const Qt::DateFormat &dateTimeFormat){
+ bool success = false;
+ auto dt = QDateTime::fromString(QDateTime::currentDateTime().toString(dateTimeFormat), dateTimeFormat);
+ if (dt.isValid()) {
+ success = true;
+ {{prefix}}SerializerSettings::setDateTimeFormatEnum(dateTimeFormat);
+ }
+ return success;
+}
QString toStringValue(const QString &value) {
return value;
}
QString toStringValue(const QDateTime &value) {
+ if ({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().isStringSet) {
+ return value.toString({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().formatString);
+ }
+
+ if ({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().isEnumSet) {
+ return value.toString({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().formatEnum);
+ }
+
// ISO 8601
- return {{prefix}}SerializerSettings::getInstance()->getDateTimeFormat().isEmpty()? value.toString(Qt::ISODate):value.toString({{prefix}}SerializerSettings::getInstance()->getDateTimeFormat());
+ return value.toString(Qt::ISODate);
}
QString toStringValue(const QByteArray &value) {
@@ -98,7 +134,16 @@ QJsonValue toJsonValue(const QString &value) {
}
QJsonValue toJsonValue(const QDateTime &value) {
- return QJsonValue(value.toString({{prefix}}SerializerSettings::getInstance()->getDateTimeFormat().isEmpty()?value.toString(Qt::ISODate):value.toString({{prefix}}SerializerSettings::getInstance()->getDateTimeFormat())));
+ if ({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().isStringSet) {
+ return QJsonValue(value.toString({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().formatString));
+ }
+
+ if ({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().isEnumSet) {
+ return QJsonValue(value.toString({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().formatEnum));
+ }
+
+ // ISO 8601
+ return QJsonValue(value.toString(Qt::ISODate));
}
QJsonValue toJsonValue(const QByteArray &value) {
@@ -151,7 +196,15 @@ bool fromStringValue(const QString &inStr, QDateTime &value) {
if (inStr.isEmpty()) {
return false;
} else {
- auto dateTime = {{prefix}}SerializerSettings::getInstance()->getDateTimeFormat().isEmpty()?QDateTime::fromString(inStr, Qt::ISODate) :QDateTime::fromString(inStr, {{prefix}}SerializerSettings::getInstance()->getDateTimeFormat());
+ QDateTime dateTime;
+ if ({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().isStringSet) {
+ dateTime = QDateTime::fromString(inStr, {{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().formatString);
+ } else if ({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().isEnumSet) {
+ dateTime = QDateTime::fromString(inStr, {{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().formatEnum);
+ } else {
+ dateTime = QDateTime::fromString(inStr, Qt::ISODate);
+ }
+
if (dateTime.isValid()) {
value.setDate(dateTime.date());
value.setTime(dateTime.time());
@@ -256,7 +309,13 @@ bool fromJsonValue(QString &value, const QJsonValue &jval) {
bool fromJsonValue(QDateTime &value, const QJsonValue &jval) {
bool ok = true;
if (!jval.isUndefined() && !jval.isNull() && jval.isString()) {
- value = {{prefix}}SerializerSettings::getInstance()->getDateTimeFormat().isEmpty()?QDateTime::fromString(jval.toString(), Qt::ISODate): QDateTime::fromString(jval.toString(), {{prefix}}SerializerSettings::getInstance()->getDateTimeFormat());
+ if ({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().isStringSet) {
+ value = QDateTime::fromString(jval.toString(), {{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().formatString);
+ } else if ({{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().isEnumSet) {
+ value = QDateTime::fromString(jval.toString(), {{prefix}}SerializerSettings::getInstance()->getCustomDateTimeFormat().formatEnum);
+ } else {
+ value = QDateTime::fromString(jval.toString(), Qt::ISODate);
+ }
ok = value.isValid();
} else {
ok = false;
diff --git a/modules/openapi-generator/src/main/resources/cpp-qt5-client/helpers-header.mustache b/modules/openapi-generator/src/main/resources/cpp-qt5-client/helpers-header.mustache
index 1607aeed2e8..6b0ad489b1c 100644
--- a/modules/openapi-generator/src/main/resources/cpp-qt5-client/helpers-header.mustache
+++ b/modules/openapi-generator/src/main/resources/cpp-qt5-client/helpers-header.mustache
@@ -11,6 +11,7 @@
#include
#include
#include
+#include
#include "{{prefix}}Enum.h"
#include "{{prefix}}HttpFileElement.h"
@@ -41,7 +42,8 @@ public:
}
};
-bool setDateTimeFormat(const QString&);
+bool setDateTimeFormat(const QString &format);
+bool setDateTimeFormat(const Qt::DateFormat &format);
template
QString toStringValue(const QList &val);
diff --git a/modules/openapi-generator/src/main/resources/cpp-rest-sdk-client/cmake-lists.mustache b/modules/openapi-generator/src/main/resources/cpp-rest-sdk-client/cmake-lists.mustache
index 66171dc81a8..b882ea0e723 100644
--- a/modules/openapi-generator/src/main/resources/cpp-rest-sdk-client/cmake-lists.mustache
+++ b/modules/openapi-generator/src/main/resources/cpp-rest-sdk-client/cmake-lists.mustache
@@ -39,7 +39,6 @@ else()
find_package(cpprestsdk REQUIRED)
find_package(Boost REQUIRED)
- find_package(pthreads REQUIRED)
endif()
# Manually set the cpprestsdk paths when not using package manager
@@ -68,9 +67,9 @@ target_link_directories(
)
if (UNIX)
- target_link_libraries(${PROJECT_NAME} PRIVATE cpprest pthread ${Boost_LIBRARIES} crypto)
+ target_link_libraries(${PROJECT_NAME} PRIVATE cpprest ${Boost_LIBRARIES} crypto)
else()
- target_link_libraries(${PROJECT_NAME} PRIVATE cpprestsdk::cpprest ${pthreads_LIBRARIES} ${Boost_LIBRARIES} bcrypt)
+ target_link_libraries(${PROJECT_NAME} PRIVATE cpprestsdk::cpprest ${Boost_LIBRARIES} bcrypt)
endif()
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14)
diff --git a/modules/openapi-generator/src/main/resources/cpp-ue4/helpers-header.mustache b/modules/openapi-generator/src/main/resources/cpp-ue4/helpers-header.mustache
index eb178e890af..67d60535987 100644
--- a/modules/openapi-generator/src/main/resources/cpp-ue4/helpers-header.mustache
+++ b/modules/openapi-generator/src/main/resources/cpp-ue4/helpers-header.mustache
@@ -105,6 +105,11 @@ inline FStringFormatArg ToStringFormatArg(const FDateTime& Value)
return FStringFormatArg(Value.ToIso8601());
}
+inline FStringFormatArg ToStringFormatArg(const FGuid& Value)
+{
+ return FStringFormatArg(Value.ToString(EGuidFormats::DigitsWithHyphens));
+}
+
inline FStringFormatArg ToStringFormatArg(const TArray& Value)
{
return FStringFormatArg(Base64UrlEncode(Value));
@@ -220,6 +225,11 @@ inline void WriteJsonValue(JsonWriter& Writer, const FDateTime& Value)
Writer->WriteValue(Value.ToIso8601());
}
+inline void WriteJsonValue(JsonWriter& Writer, const FGuid& Value)
+{
+ Writer->WriteValue(Value.ToString(EGuidFormats::DigitsWithHyphens));
+}
+
inline void WriteJsonValue(JsonWriter& Writer, const Model& Value)
{
Value.WriteJson(Writer);
@@ -281,6 +291,17 @@ inline bool TryGetJsonValue(const TSharedPtr& JsonValue, FDateTime&
return false;
}
+inline bool TryGetJsonValue(const TSharedPtr& JsonValue, FGuid& Value)
+{
+ FString TmpValue;
+ if (JsonValue->TryGetString(TmpValue))
+ {
+ return FGuid::Parse(TmpValue, Value);
+ }
+ else
+ return false;
+}
+
inline bool TryGetJsonValue(const TSharedPtr& JsonValue, bool& Value)
{
bool TmpValue;
diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/README.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/README.mustache
index e9e3655c5c2..c5f3c0eadfa 100644
--- a/modules/openapi-generator/src/main/resources/csharp-netcore/README.mustache
+++ b/modules/openapi-generator/src/main/resources/csharp-netcore/README.mustache
@@ -55,7 +55,8 @@ Install-Package CompareNETObjects
```
{{#useRestSharp}}
-NOTE: RestSharp versions greater than 105.1.0 have a bug which causes file uploads to fail. See [RestSharp#742](https://github.com/restsharp/RestSharp/issues/742)
+NOTE: RestSharp versions greater than 105.1.0 have a bug which causes file uploads to fail. See [RestSharp#742](https://github.com/restsharp/RestSharp/issues/742).
+NOTE: RestSharp for .Net Core creates a new socket for each api call, which can lead to a socket exhaustion problem. See [RestSharp#1406](https://github.com/restsharp/RestSharp/issues/1406).
{{/useRestSharp}}
@@ -102,7 +103,10 @@ c.Proxy = webProxy;
```
{{#useHttpClient}}
-To use your own HttpClient instances just pass them to the ApiClass constructor.
+### Connections
+Each ApiClass (properly the ApiClient inside it) will create an istance of HttpClient. It will use that for the entire lifecycle and dispose it when called the Dispose method.
+
+To better manager the connections it's a common practice to reuse the HttpClient and HttpClientHander (see [here](https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests#issues-with-the-original-httpclient-class-available-in-net) for details). To use your own HttpClient instance just pass it to the ApiClass constructor.
```csharp
HttpClientHandler yourHandler = new HttpClientHandler();
@@ -110,17 +114,20 @@ HttpClient yourHttpClient = new HttpClient(yourHandler);
var api = new YourApiClass(yourHttpClient, yourHandler);
```
-If you want to use an HttpClient and don't have access to the handler, for example in a DI context in aspnetcore when
-using IHttpClientFactory. You need to disable the features that require handler access:
+If you want to use an HttpClient and don't have access to the handler, for example in a DI context in Asp.net Core when using IHttpClientFactory.
```csharp
HttpClient yourHttpClient = new HttpClient();
-var api = new YourApiClass(yourHttpClient, null, true);
+var api = new YourApiClass(yourHttpClient);
```
+You'll loose some configuration settings, the features affected are: Setting and Retrieving Cookies, Client Certificates, Proxy settings. You need to either manually handle those in your setup of the HttpClient or they won't be available.
-The features affected are: Setting and Retrieving Cookies, Client Certificates, Proxy settings.
-You need to either manually handle those in your setup of the HttpClient or they won't be available.
+Here an example of DI setup in a sample web project:
+```csharp
+services.AddHttpClient(httpClient =>
+ new PetApi(httpClient));
+```
{{/useHttpClient}}
diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/TestProject.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/TestProject.mustache
index bab424f90f8..b1a50ae778e 100644
--- a/modules/openapi-generator/src/main/resources/csharp-netcore/TestProject.mustache
+++ b/modules/openapi-generator/src/main/resources/csharp-netcore/TestProject.mustache
@@ -17,7 +17,7 @@
Properties
{{testPackageName}}
{{testPackageName}}
- {{testTargetFramework}}
+ {{testTargetFramework}}
false
512
diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/ApiClient.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/ApiClient.mustache
index 23ba41d1a0f..619bcb6bfbb 100644
--- a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/ApiClient.mustache
+++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/ApiClient.mustache
@@ -161,17 +161,17 @@ namespace {{packageName}}.Client
/// Provides a default implementation of an Api client (both synchronous and asynchronous implementatios),
/// encapsulating general REST accessor use cases.
///
+ ///
+ /// The Dispose method will manage the HttpClient lifecycle when not passed by constructor.
+ ///
{{>visibility}} partial class ApiClient : IDisposable, ISynchronousClient{{#supportsAsync}}, IAsynchronousClient{{/supportsAsync}}
{
private readonly String _baseUrl;
private readonly HttpClientHandler _httpClientHandler;
- private readonly bool _disposeHandler;
- private readonly HttpClient _httpClient;
+ private readonly HttpClient _httpClient;
private readonly bool _disposeClient;
- private readonly bool _disableHandlerFeatures;
-
///
/// Specifies the settings on a object.
/// These settings can be adjusted to accomodate custom serialization rules.
@@ -192,37 +192,63 @@ namespace {{packageName}}.Client
///
/// Initializes a new instance of the , defaulting to the global configurations' base url.
///
- /// An instance of HttpClient
- /// An instance of HttpClientHandler that is used by HttpClient
- /// Disable ApiClient features that require access to the HttpClientHandler
- public ApiClient(HttpClient client = null, HttpClientHandler handler = null, bool disableHandlerFeatures = false) :
- this({{packageName}}.Client.GlobalConfiguration.Instance.BasePath, client, handler, disableHandlerFeatures)
- {
+ [Obsolete("Constructors without HttpClient have non-trivial drawbacks and are thus considered deprecated. Check README.md for details.")]
+ public ApiClient() :
+ this({{packageName}}.Client.GlobalConfiguration.Instance.BasePath)
+ {
}
-
+
///
- /// Initializes a new instance of the
+ /// Initializes a new instance of the .
///
/// The target service's base path in URL format.
- /// An instance of HttpClient
- /// An instance of HttpClientHandler that is used by HttpClient
- /// Disable ApiClient features that require access to the HttpClientHandler
///
- public ApiClient(String basePath, HttpClient client = null, HttpClientHandler handler = null, bool disableHandlerFeatures = false)
- {
- if (string.IsNullOrEmpty(basePath))
- throw new ArgumentException("basePath cannot be empty");
+ [Obsolete("Constructors without HttpClient have non-trivial drawbacks and are thus considered deprecated. Check README.md for details.")]
+ public ApiClient(String basePath)
+ {
+ if (string.IsNullOrEmpty(basePath)) throw new ArgumentException("basePath cannot be empty");
+ _httpClientHandler = new HttpClientHandler();
+ _httpClient = new HttpClient(_httpClientHandler, true);
+ _disposeClient = true;
+ _baseUrl = basePath;
+ }
+
+ ///
+ /// Initializes a new instance of the , defaulting to the global configurations' base url.
+ ///
+ /// An instance of HttpClient.
+ /// An optional instance of HttpClientHandler that is used by HttpClient.
+ ///
+ ///
+ /// Some configuration settings will not be applied without passing an HttpClientHandler.
+ /// The features affected are: Setting and Retrieving Cookies, Client Certificates, Proxy settings.
+ ///
+ public ApiClient(HttpClient client, HttpClientHandler handler = null) :
+ this(client, {{packageName}}.Client.GlobalConfiguration.Instance.BasePath, handler)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the .
+ ///
+ /// An instance of HttpClient.
+ /// The target service's base path in URL format.
+ /// An optional instance of HttpClientHandler that is used by HttpClient.
+ ///
+ ///
+ ///
+ /// Some configuration settings will not be applied without passing an HttpClientHandler.
+ /// The features affected are: Setting and Retrieving Cookies, Client Certificates, Proxy settings.
+ ///
+ public ApiClient(HttpClient client, String basePath, HttpClientHandler handler = null)
+ {
+ if (client == null) throw new ArgumentNullException("client cannot be null");
+ if (string.IsNullOrEmpty(basePath)) throw new ArgumentException("basePath cannot be empty");
+
+ _httpClientHandler = handler;
+ _httpClient = client;
_baseUrl = basePath;
- if((client != null && handler == null) && !disableHandlerFeatures) {
- throw new ArgumentException("If providing HttpClient, you also need to provide its handler or disable features requiring the handler, see README.md");
- }
-
- _disableHandlerFeatures = disableHandlerFeatures;
- _httpClientHandler = handler ?? new HttpClientHandler();
- _disposeHandler = handler == null;
- _httpClient = client ?? new HttpClient(_httpClientHandler, false);
- _disposeClient = client == null;
}
///
@@ -233,9 +259,6 @@ namespace {{packageName}}.Client
if(_disposeClient) {
_httpClient.Dispose();
}
- if(_disposeHandler) {
- _httpClientHandler.Dispose();
- }
}
/// Prepares multipart/form-data content
@@ -373,10 +396,10 @@ namespace {{packageName}}.Client
return request;
}
- partial void InterceptRequest(HttpRequestMessage req, HttpClientHandler handler);
+ partial void InterceptRequest(HttpRequestMessage req);
partial void InterceptResponse(HttpRequestMessage req, HttpResponseMessage response);
- private ApiResponse ToApiResponse(HttpResponseMessage response, object responseData, HttpClientHandler handler, Uri uri)
+ private ApiResponse ToApiResponse(HttpResponseMessage response, object responseData, Uri uri)
{
T result = (T) responseData;
string rawContent = response.Content.ToString();
@@ -405,18 +428,15 @@ namespace {{packageName}}.Client
}
}
- if(!_disableHandlerFeatures)
+ if (_httpClientHandler != null && response != null)
{
- if (response != null)
- {
- try {
- foreach (Cookie cookie in handler.CookieContainer.GetCookies(uri))
- {
- transformed.Cookies.Add(cookie);
- }
+ try {
+ foreach (Cookie cookie in _httpClientHandler.CookieContainer.GetCookies(uri))
+ {
+ transformed.Cookies.Add(cookie);
}
- catch (PlatformNotSupportedException) {}
}
+ catch (PlatformNotSupportedException) {}
}
return transformed;
@@ -431,8 +451,6 @@ namespace {{packageName}}.Client
IReadableConfiguration configuration,
System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken))
{
- var handler = _httpClientHandler;
- var client = _httpClient;
var deserializer = new CustomJsonCodec(SerializerSettings, configuration);
var finalToken = cancellationToken;
@@ -442,29 +460,31 @@ namespace {{packageName}}.Client
var tokenSource = new CancellationTokenSource(configuration.Timeout);
finalToken = CancellationTokenSource.CreateLinkedTokenSource(finalToken, tokenSource.Token).Token;
}
- if(!_disableHandlerFeatures) {
- if (configuration.Proxy != null)
- {
- handler.Proxy = configuration.Proxy;
- }
- if (configuration.ClientCertificates != null)
- {
- handler.ClientCertificates.AddRange(configuration.ClientCertificates);
- }
+ if (configuration.Proxy != null)
+ {
+ if(_httpClientHandler == null) throw new InvalidOperationException("Configuration `Proxy` not supported when the client is explicitly created without an HttpClientHandler, use the proper constructor.");
+ _httpClientHandler.Proxy = configuration.Proxy;
+ }
+
+ if (configuration.ClientCertificates != null)
+ {
+ if(_httpClientHandler == null) throw new InvalidOperationException("Configuration `ClientCertificates` not supported when the client is explicitly created without an HttpClientHandler, use the proper constructor.");
+ _httpClientHandler.ClientCertificates.AddRange(configuration.ClientCertificates);
}
var cookieContainer = req.Properties.ContainsKey("CookieContainer") ? req.Properties["CookieContainer"] as List : null;
if (cookieContainer != null)
{
+ if(_httpClientHandler == null) throw new InvalidOperationException("Request property `CookieContainer` not supported when the client is explicitly created without an HttpClientHandler, use the proper constructor.");
foreach (var cookie in cookieContainer)
{
- handler.CookieContainer.Add(cookie);
+ _httpClientHandler.CookieContainer.Add(cookie);
}
}
- InterceptRequest(req, handler);
+ InterceptRequest(req);
HttpResponseMessage response;
{{#supportsRetry}}
@@ -472,7 +492,7 @@ namespace {{packageName}}.Client
{
var policy = RetryConfiguration.AsyncRetryPolicy;
var policyResult = await policy
- .ExecuteAndCaptureAsync(() => client.SendAsync(req, cancellationToken))
+ .ExecuteAndCaptureAsync(() => _httpClient.SendAsync(req, cancellationToken))
.ConfigureAwait(false);
response = (policyResult.Outcome == OutcomeType.Successful) ?
policyResult.Result : new HttpResponseMessage()
@@ -484,7 +504,7 @@ namespace {{packageName}}.Client
else
{
{{/supportsRetry}}
- response = await client.SendAsync(req, cancellationToken).ConfigureAwait(false);
+ response = await _httpClient.SendAsync(req, cancellationToken).ConfigureAwait(false);
{{#supportsRetry}}
}
{{/supportsRetry}}
@@ -503,7 +523,7 @@ namespace {{packageName}}.Client
InterceptResponse(req, response);
- var result = ToApiResponse(response, responseData, handler, req.RequestUri);
+ var result = ToApiResponse(response, responseData, req.RequestUri);
return result;
}
diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/api.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/api.mustache
index 4bb08fb6820..efa52cfbd41 100644
--- a/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/api.mustache
+++ b/modules/openapi-generator/src/main/resources/csharp-netcore/libraries/httpclient/api.mustache
@@ -107,29 +107,26 @@ namespace {{packageName}}.{{apiPackage}}
///
/// Initializes a new instance of the class.
///
- /// An instance of HttpClient
- /// An instance of HttpClientHandler that is used by HttpClient
- /// Disable ApiClient features that require access to the HttpClientHandler
///
- public {{classname}}(HttpClient client = null, HttpClientHandler handler = null, bool disableHandlerFeatures = false) : this((string)null, client, handler, disableHandlerFeatures)
+ [Obsolete("Constructors without HttpClient have non-trivial drawbacks and are thus considered deprecated. Check README.md for details.")]
+ public {{classname}}() : this((string)null)
{
-
}
///
/// Initializes a new instance of the class.
///
- /// An instance of HttpClient
- /// An instance of HttpClientHandler that is used by HttpClient
- /// Disable ApiClient features that require access to the HttpClientHandler
+ /// The target service's base path in URL format.
+ ///
///
- public {{classname}}(String basePath, HttpClient client = null, HttpClientHandler handler = null, bool disableHandlerFeatures = false)
+ [Obsolete("Constructors without HttpClient have non-trivial drawbacks and are thus considered deprecated. Check README.md for details.")]
+ public {{classname}}(String basePath)
{
this.Configuration = {{packageName}}.Client.Configuration.MergeConfigurations(
{{packageName}}.Client.GlobalConfiguration.Instance,
new {{packageName}}.Client.Configuration { BasePath = basePath }
);
- this.ApiClient = new {{packageName}}.Client.ApiClient(this.Configuration.BasePath, client, handler, disableHandlerFeatures);
+ this.ApiClient = new {{packageName}}.Client.ApiClient(this.Configuration.BasePath);
this.Client = this.ApiClient;
{{#supportsAsync}}
this.AsynchronousClient = this.ApiClient;
@@ -138,15 +135,13 @@ namespace {{packageName}}.{{apiPackage}}
}
///
- /// Initializes a new instance of the class
- /// using Configuration object
+ /// Initializes a new instance of the class using Configuration object.
///
- /// An instance of Configuration
- /// An instance of HttpClient
- /// An instance of HttpClientHandler that is used by HttpClient
- /// Disable ApiClient features that require access to the HttpClientHandler
+ /// An instance of Configuration.
+ ///
///
- public {{classname}}({{packageName}}.Client.Configuration configuration, HttpClient client = null, HttpClientHandler handler = null, bool disableHandlerFeatures = false)
+ [Obsolete("Constructors without HttpClient have non-trivial drawbacks and are thus considered deprecated. Check README.md for details.")]
+ public {{classname}}({{packageName}}.Client.Configuration configuration)
{
if (configuration == null) throw new ArgumentNullException("configuration");
@@ -154,7 +149,80 @@ namespace {{packageName}}.{{apiPackage}}
{{packageName}}.Client.GlobalConfiguration.Instance,
configuration
);
- this.ApiClient = new {{packageName}}.Client.ApiClient(this.Configuration.BasePath, client, handler, disableHandlerFeatures);
+ this.ApiClient = new {{packageName}}.Client.ApiClient(this.Configuration.BasePath);
+ this.Client = this.ApiClient;
+ {{#supportsAsync}}
+ this.AsynchronousClient = this.ApiClient;
+ {{/supportsAsync}}
+ ExceptionFactory = {{packageName}}.Client.Configuration.DefaultExceptionFactory;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// An instance of HttpClient.
+ /// An optional instance of HttpClientHandler that is used by HttpClient.
+ ///
+ ///
+ ///
+ /// Some configuration settings will not be applied without passing an HttpClientHandler.
+ /// The features affected are: Setting and Retrieving Cookies, Client Certificates, Proxy settings.
+ ///
+ public {{classname}}(HttpClient client, HttpClientHandler handler = null) : this(client, (string)null, handler)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// An instance of HttpClient.
+ /// The target service's base path in URL format.
+ /// An optional instance of HttpClientHandler that is used by HttpClient.
+ ///
+ ///
+ ///
+ ///
+ /// Some configuration settings will not be applied without passing an HttpClientHandler.
+ /// The features affected are: Setting and Retrieving Cookies, Client Certificates, Proxy settings.
+ ///
+ public {{classname}}(HttpClient client, String basePath, HttpClientHandler handler = null)
+ {
+ if (client == null) throw new ArgumentNullException("client");
+
+ this.Configuration = {{packageName}}.Client.Configuration.MergeConfigurations(
+ {{packageName}}.Client.GlobalConfiguration.Instance,
+ new {{packageName}}.Client.Configuration { BasePath = basePath }
+ );
+ this.ApiClient = new {{packageName}}.Client.ApiClient(client, this.Configuration.BasePath, handler);
+ this.Client = this.ApiClient;
+ {{#supportsAsync}}
+ this.AsynchronousClient = this.ApiClient;
+ {{/supportsAsync}}
+ this.ExceptionFactory = {{packageName}}.Client.Configuration.DefaultExceptionFactory;
+ }
+
+ ///
+ /// Initializes a new instance of the class using Configuration object.
+ ///
+ /// An instance of HttpClient.
+ /// An instance of Configuration.
+ /// An optional instance of HttpClientHandler that is used by HttpClient.
+ ///
+ ///
+ ///
+ /// Some configuration settings will not be applied without passing an HttpClientHandler.
+ /// The features affected are: Setting and Retrieving Cookies, Client Certificates, Proxy settings.
+ ///
+ public {{classname}}(HttpClient client, {{packageName}}.Client.Configuration configuration, HttpClientHandler handler = null)
+ {
+ if (configuration == null) throw new ArgumentNullException("configuration");
+ if (client == null) throw new ArgumentNullException("client");
+
+ this.Configuration = {{packageName}}.Client.Configuration.MergeConfigurations(
+ {{packageName}}.Client.GlobalConfiguration.Instance,
+ configuration
+ );
+ this.ApiClient = new {{packageName}}.Client.ApiClient(client, this.Configuration.BasePath, handler);
this.Client = this.ApiClient;
{{#supportsAsync}}
this.AsynchronousClient = this.ApiClient;
@@ -169,6 +237,7 @@ namespace {{packageName}}.{{apiPackage}}
/// The client interface for synchronous API access.{{#supportsAsync}}
/// The client interface for asynchronous API access.{{/supportsAsync}}
/// The configuration object.
+ ///
public {{classname}}({{packageName}}.Client.ISynchronousClient client, {{#supportsAsync}}{{packageName}}.Client.IAsynchronousClient asyncClient, {{/supportsAsync}}{{packageName}}.Client.IReadableConfiguration configuration)
{
if (client == null) throw new ArgumentNullException("client");
diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/modelGeneric.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/modelGeneric.mustache
index c3333605694..3ecfa611d68 100644
--- a/modules/openapi-generator/src/main/resources/csharp-netcore/modelGeneric.mustache
+++ b/modules/openapi-generator/src/main/resources/csharp-netcore/modelGeneric.mustache
@@ -24,6 +24,7 @@
{{/complexType}}
{{/isEnum}}
{{#isEnum}}
+
///
/// {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}}
///
diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/netcore_project.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/netcore_project.mustache
index cdc1b85e584..7d77d34b4d8 100644
--- a/modules/openapi-generator/src/main/resources/csharp-netcore/netcore_project.mustache
+++ b/modules/openapi-generator/src/main/resources/csharp-netcore/netcore_project.mustache
@@ -2,7 +2,7 @@
false
- {{targetFramework}}
+ {{targetFramework}}
{{packageName}}
{{packageName}}
Library
diff --git a/modules/openapi-generator/src/main/resources/csharp-netcore/netcore_testproject.mustache b/modules/openapi-generator/src/main/resources/csharp-netcore/netcore_testproject.mustache
index 48eaf5a20cc..b20a94c76c1 100644
--- a/modules/openapi-generator/src/main/resources/csharp-netcore/netcore_testproject.mustache
+++ b/modules/openapi-generator/src/main/resources/csharp-netcore/netcore_testproject.mustache
@@ -3,7 +3,7 @@
{{testPackageName}}
{{testPackageName}}
- {{testTargetFramework}}
+ {{testTargetFramework}}
false
diff --git a/modules/openapi-generator/src/main/resources/dart-dio/api.mustache b/modules/openapi-generator/src/main/resources/dart-dio/api.mustache
index 38f4deb96f8..dff1dcd4235 100644
--- a/modules/openapi-generator/src/main/resources/dart-dio/api.mustache
+++ b/modules/openapi-generator/src/main/resources/dart-dio/api.mustache
@@ -4,10 +4,8 @@ import 'package:dio/dio.dart';
import 'package:built_value/serializer.dart';
{{#operations}}
-{{#modelImports}}import 'package:{{pubName}}/model/{{.}}.dart';
-{{/modelImports}}
-{{#fullImports}}import '{{.}}';
-{{/fullImports}}
+{{#imports}}import '{{.}}';
+{{/imports}}
class {{classname}} {
diff --git a/modules/openapi-generator/src/main/resources/dart-dio/pubspec.mustache b/modules/openapi-generator/src/main/resources/dart-dio/pubspec.mustache
index 1d1a328affe..025230b7357 100644
--- a/modules/openapi-generator/src/main/resources/dart-dio/pubspec.mustache
+++ b/modules/openapi-generator/src/main/resources/dart-dio/pubspec.mustache
@@ -1,16 +1,22 @@
name: {{pubName}}
version: {{pubVersion}}
description: {{pubDescription}}
+homepage: {{pubHomepage}}
+authors:
+ - '{{{pubAuthor}}} <{{{pubAuthorEmail}}}>'
+
environment:
- sdk: '>=2.7.0 <3.0.0'
+ sdk: '>=2.7.0 <3.0.0'
+
dependencies:
- dio: '^3.0.9'
- built_value: '>=7.1.0 <8.0.0'
- built_collection: '>=4.3.2 <5.0.0'
+ dio: '^3.0.9'
+ built_value: '>=7.1.0 <8.0.0'
+ built_collection: '>=4.3.2 <5.0.0'
{{#timeMachine}}
- time_machine: '^0.9.12'
+ time_machine: '^0.9.12'
{{/timeMachine}}
+
dev_dependencies:
- built_value_generator: '>=7.1.0 <8.0.0'
- build_runner: any
- test: '>=1.3.0 <1.16.0'
+ built_value_generator: '>=7.1.0 <8.0.0'
+ build_runner: any
+ test: '>=1.3.0 <1.16.0'
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/README.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/README.mustache
index 454bd6ccdb9..3ef0679e726 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/README.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/README.mustache
@@ -21,25 +21,32 @@ For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
* Dart 2.12.0 or later OR Flutter 1.26.0 or later
* Dio 4.0.0+
+{{#useDateLibTimeMachine}}
* timemachine option currently **DOES NOT** support sound null-safety and may not work
+{{/useDateLibTimeMachine}}
## Installation & Usage
-### Github
-If this Dart package is published to Github, please include the following in pubspec.yaml
-```
-name: {{pubName}}
-version: {{pubVersion}}
-description: {{pubDescription}}
+### pub.dev
+To use the package from [pub.dev](https://pub.dev), please include the following in pubspec.yaml
+```yaml
dependencies:
- {{pubName}}:
- git: https://github.com/{{gitUserId}}/{{gitRepoId}}.git
- version: 'any'
+ {{pubName}}: {{pubVersion}}
```
-### Local
-To use the package in your local drive, please include the following in pubspec.yaml
+### Github
+If this Dart package is published to Github, please include the following in pubspec.yaml
+```yaml
+dependencies:
+ {{pubName}}:
+ git:
+ url: https://github.com/{{gitUserId}}/{{gitRepoId}}.git
+ #ref: main
```
+
+### Local development
+To use the package from your local drive, please include the following in pubspec.yaml
+```yaml
dependencies:
{{pubName}}:
path: /path/to/{{pubName}}
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache
index 8deca6ce000..34cf9554991 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache
@@ -5,10 +5,8 @@ import 'dart:async';
import 'package:dio/dio.dart';
{{#operations}}
-{{#modelImports}}import 'package:{{pubName}}/src/model/{{.}}.dart';
-{{/modelImports}}
-{{#fullImports}}import '{{.}}';
-{{/fullImports}}
+{{#imports}}import '{{.}}';
+{{/imports}}
class {{classname}} {
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/lib.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/lib.mustache
index ff543662653..32f6a54b1a6 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/lib.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/lib.mustache
@@ -3,7 +3,8 @@ export 'package:{{pubName}}/src/api.dart';
export 'package:{{pubName}}/src/auth/api_key_auth.dart';
export 'package:{{pubName}}/src/auth/basic_auth.dart';
export 'package:{{pubName}}/src/auth/oauth.dart';
-{{#useBuiltValue}}export 'package:{{pubName}}/src/serializers.dart';{{/useBuiltValue}}
+{{#useBuiltValue}}export 'package:{{pubName}}/src/serializers.dart';
+{{#useDateLibCore}}export 'package:{{pubName}}/src/model/date.dart';{{/useDateLibCore}}{{/useBuiltValue}}
{{#apiInfo}}{{#apis}}export 'package:{{pubName}}/src/api/{{classFilename}}.dart';
{{/apis}}{{/apiInfo}}
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache
index 7e466cc87f5..b2eef72f91e 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache
@@ -1,6 +1,9 @@
name: {{pubName}}
version: {{pubVersion}}
description: {{pubDescription}}
+homepage: {{pubHomepage}}
+authors:
+ - '{{{pubAuthor}}} <{{{pubAuthorEmail}}}>'
environment:
sdk: '>=2.12.0 <3.0.0'
@@ -8,7 +11,7 @@ environment:
dependencies:
dio: '>=4.0.0 <5.0.0'
{{#useBuiltValue}}
- built_value: '>=8.0.3 <9.0.0'
+ built_value: '>=8.0.4 <9.0.0'
built_collection: '>=5.0.0 <6.0.0'
{{/useBuiltValue}}
{{#useDateLibTimeMachine}}
@@ -17,7 +20,7 @@ dependencies:
dev_dependencies:
{{#useBuiltValue}}
- built_value_generator: '>=8.0.3 <9.0.0'
+ built_value_generator: '>=8.0.4 <9.0.0'
build_runner: any
{{/useBuiltValue}}
test: '>=1.16.0 <1.17.0'
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/date.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/date.mustache
new file mode 100644
index 00000000000..c3a87eae259
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/date.mustache
@@ -0,0 +1,69 @@
+/// A gregorian calendar date generated by
+/// OpenAPI generator to differentiate
+/// between [DateTime] and [Date] formats.
+class Date implements Comparable {
+ final int year;
+
+ /// January is 1.
+ final int month;
+
+ /// First day is 1.
+ final int day;
+
+ Date(this.year, this.month, this.day);
+
+ /// The current date
+ static Date now({bool utc = false}) {
+ var now = DateTime.now();
+ if (utc) {
+ now = now.toUtc();
+ }
+ return now.toDate();
+ }
+
+ /// Convert to a [DateTime].
+ DateTime toDateTime({bool utc = false}) {
+ if (utc) {
+ DateTime.utc(year, month, day);
+ }
+ return DateTime(year, month, day);
+ }
+
+ @override
+ int compareTo(Date other) {
+ int d = year.compareTo(other.year);
+ if (d != 0) {
+ return d;
+ }
+ d = month.compareTo(other.month);
+ if (d != 0) {
+ return d;
+ }
+ return day.compareTo(other.day);
+ }
+
+ @override
+ bool operator ==(Object other) =>
+ identical(this, other) ||
+ other is Date &&
+ runtimeType == other.runtimeType &&
+ year == other.year &&
+ month == other.month &&
+ day == other.day;
+
+ @override
+ int get hashCode => year.hashCode ^ month.hashCode ^ day.hashCode;
+
+ @override
+ String toString() {
+ final yyyy = year.toString();
+ final mm = month.toString().padLeft(2, '0');
+ final dd = day.toString().padLeft(2, '0');
+
+ return '$yyyy-$mm-$dd';
+ }
+}
+
+extension DateTimeToDate on DateTime {
+ Date toDate() => Date(year, month, day);
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/date_serializer.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/date_serializer.mustache
new file mode 100644
index 00000000000..b5f0ed32c22
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/date_serializer.mustache
@@ -0,0 +1,28 @@
+{{>header}}
+import 'package:built_collection/built_collection.dart';
+import 'package:built_value/serializer.dart';
+import 'package:{{pubName}}/src/model/date.dart';
+
+class DateSerializer implements PrimitiveSerializer {
+
+ const DateSerializer();
+
+ @override
+ Iterable get types => BuiltList.of([Date]);
+
+ @override
+ String get wireName => 'Date';
+
+ @override
+ Date deserialize(Serializers serializers, Object serialized,
+ {FullType specifiedType = FullType.unspecified}) {
+ final parsed = DateTime.parse(serialized as String);
+ return Date(parsed.year, parsed.month, parsed.day);
+ }
+
+ @override
+ Object serialize(Serializers serializers, Date date,
+ {FullType specifiedType = FullType.unspecified}) {
+ return date.toString();
+ }
+}
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/local_date_serializer.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/offset_date_serializer.mustache
similarity index 96%
rename from modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/local_date_serializer.mustache
rename to modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/offset_date_serializer.mustache
index 68cfd5e31c6..2698caf0f49 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/local_date_serializer.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/offset_date_serializer.mustache
@@ -8,7 +8,7 @@ class OffsetDateSerializer implements PrimitiveSerializer {
const OffsetDateSerializer();
@override
- Iterable get types => BuiltList([OffsetDate]);
+ Iterable get types => BuiltList.of([OffsetDate]);
@override
String get wireName => 'OffsetDate';
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/serializers.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/serializers.mustache
index afca0bc138f..10925bc1112 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/serializers.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/serializers.mustache
@@ -1,11 +1,15 @@
{{>header}}
+// ignore_for_file: unused_import
+
import 'package:built_collection/built_collection.dart';
import 'package:built_value/json_object.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
-{{#useDateLibCore}}import 'package:built_value/iso_8601_date_time_serializer.dart';{{/useDateLibCore}}
+{{#useDateLibCore}}import 'package:built_value/iso_8601_date_time_serializer.dart';
+import 'package:{{pubName}}/src/date_serializer.dart';
+import 'package:{{pubName}}/src/model/date.dart';{{/useDateLibCore}}
{{#useDateLibTimeMachine}}import 'package:time_machine/time_machine.dart';
-import 'package:{{pubName}}/src/local_date_serializer.dart';{{/useDateLibTimeMachine}}
+import 'package:{{pubName}}/src/offset_date_serializer.dart';{{/useDateLibTimeMachine}}
{{#models}}{{#model}}import 'package:{{pubName}}/src/model/{{classFilename}}.dart';
{{/model}}{{/models}}
part 'serializers.g.dart';
@@ -25,8 +29,9 @@ Serializers serializers = (_$serializers.toBuilder(){{#apiInfo}}{{#apis}}{{#seri
{{/isMap}}
){{/serializers}}{{/apis}}{{/apiInfo}}{{#useDateLibTimeMachine}}
..add(const OffsetDateSerializer())
- ..add(const OffsetDateTimeSerializer()){{/useDateLibTimeMachine}}
- ..add(Iso8601DateTimeSerializer()))
+ ..add(const OffsetDateTimeSerializer()){{/useDateLibTimeMachine}}{{#useDateLibCore}}
+ ..add(const DateSerializer())
+ ..add(Iso8601DateTimeSerializer())){{/useDateLibCore}}
.build();
Serializers standardSerializers =
diff --git a/modules/openapi-generator/src/main/resources/dart2/api.mustache b/modules/openapi-generator/src/main/resources/dart2/api.mustache
index 61ecab963b6..d99ba2b325f 100644
--- a/modules/openapi-generator/src/main/resources/dart2/api.mustache
+++ b/modules/openapi-generator/src/main/resources/dart2/api.mustache
@@ -178,7 +178,7 @@ class {{{classname}}} {
Future<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}> {{{nickname}}}({{#allParams}}{{#required}}{{{dataType}}} {{{paramName}}}{{^-last}}, {{/-last}}{{/required}}{{/allParams}}{{#hasOptionalParams}}{ {{#allParams}}{{^required}}{{{dataType}}} {{{paramName}}}{{^-last}}, {{/-last}}{{/required}}{{/allParams}} }{{/hasOptionalParams}}) async {
final response = await {{{nickname}}}WithHttpInfo({{#allParams}}{{#required}}{{{paramName}}}{{^-last}}, {{/-last}}{{/required}}{{/allParams}}{{#hasOptionalParams}} {{#allParams}}{{^required}}{{{paramName}}}: {{{paramName}}}{{^-last}}, {{/-last}}{{/required}}{{/allParams}} {{/hasOptionalParams}});
if (response.statusCode >= HttpStatus.badRequest) {
- throw ApiException(response.statusCode, _decodeBodyBytes(response));
+ throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
{{#returnType}}
// When a remote server returns no body with a status of 204, we shall not decode it.
@@ -187,16 +187,16 @@ class {{{classname}}} {
if (response.body != null && response.statusCode != HttpStatus.noContent) {
{{#native_serialization}}
{{#isArray}}
- return (apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}') as List)
+ return (await apiClient.deserializeAsync(await _decodeBodyBytes(response), '{{{returnType}}}') as List)
.cast<{{{returnBaseType}}}>()
.{{#uniqueItems}}toSet(){{/uniqueItems}}{{^uniqueItems}}toList(growable: false){{/uniqueItems}};
{{/isArray}}
{{^isArray}}
{{#isMap}}
- return {{{returnType}}}.from(apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}'));
+ return {{{returnType}}}.from(await apiClient.deserializeAsync(await _decodeBodyBytes(response), '{{{returnType}}}'),);
{{/isMap}}
{{^isMap}}
- return apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}') as {{{returnType}}};
+ return await apiClient.deserializeAsync(await _decodeBodyBytes(response), '{{{returnType}}}',) as {{{returnType}}};
{{/isMap}}{{/isArray}}{{/native_serialization}}{{#json_serializable}}
{{#isArray}}
{{#uniqueItems}}
diff --git a/modules/openapi-generator/src/main/resources/dart2/api_client.mustache b/modules/openapi-generator/src/main/resources/dart2/api_client.mustache
index a5d3b0948e7..167b6951e01 100644
--- a/modules/openapi-generator/src/main/resources/dart2/api_client.mustache
+++ b/modules/openapi-generator/src/main/resources/dart2/api_client.mustache
@@ -51,17 +51,16 @@ class ApiClient {
Map get defaultHeaderMap => _defaultHeaderMap;
- /// returns an unmodifiable view of the authentications, since none should be added
- /// nor deleted
- Map get authentications =>
- Map.unmodifiable(_authentications);
+ /// Returns an unmodifiable [Map] of the authentications, since none should be added
+ /// or deleted.
+ Map get authentications => Map.unmodifiable(_authentications);
T getAuthentication(String name) {
final authentication = _authentications[name];
return authentication is T ? authentication : null;
}
- // We don’t use a Map for queryParams.
+ // We don't use a Map for queryParams.
// If collectionFormat is 'multi', a key might appear multiple times.
Future invokeAPI(
String path,
@@ -92,7 +91,7 @@ class ApiClient {
}
try {
- // Special case for uploading a single file which isn’t a 'multipart/form-data'.
+ // Special case for uploading a single file which isn't a 'multipart/form-data'.
if (
body is MultipartFile && (nullableContentType == null ||
!nullableContentType.toLowerCase().startsWith('multipart/form-data'))
@@ -122,7 +121,7 @@ class ApiClient {
final msgBody = nullableContentType == 'application/x-www-form-urlencoded'
? formParams
- : serialize(body);
+ : await serializeAsync(body);
final nullableHeaderParams = headerParams.isEmpty ? null : headerParams;
switch(method) {
@@ -147,9 +146,48 @@ class ApiClient {
throw ApiException(HttpStatus.badRequest, 'Invalid HTTP operation: $method $path',);
}
+{{#native_serialization}}
+
+ Future deserializeAsync(String json, String targetType, {bool growable}) async =>
+ // ignore: deprecated_member_use_from_same_package
+ deserialize(json, targetType, growable: growable);
+
+ @Deprecated('Scheduled for removal in OpenAPI Generator 6.x. Use deserializeAsync() instead.')
+ dynamic deserialize(String json, String targetType, {bool growable}) {
+ // Remove all spaces. Necessary for regular expressions as well.
+ targetType = targetType.replaceAll(' ', ''); // ignore: parameter_assignments
+
+ // If the expected target type is String, nothing to do...
+ return targetType == 'String'
+ ? json
+ : _deserialize(jsonDecode(json), targetType, growable: growable == true);
+ }
+{{/native_serialization}}
+
+ // ignore: deprecated_member_use_from_same_package
+ Future serializeAsync(Object value) async => serialize(value);
+
+ @Deprecated('Scheduled for removal in OpenAPI Generator 6.x. Use serializeAsync() instead.')
+ String serialize(Object value) => value == null ? '' : json.encode(value);
+
+ /// Update query and header parameters based on authentication settings.
+ /// @param authNames The authentications to apply
+ void _updateParamsForAuth(
+ List authNames,
+ List queryParams,
+ Map headerParams,
+ ) {
+ authNames.forEach((authName) {
+ final auth = _authentications[authName];
+ if (auth == null) {
+ throw ArgumentError('Authentication undefined: $authName');
+ }
+ auth.applyToParams(queryParams, headerParams);
+ });
+ }
{{#native_serialization}}
- dynamic _deserialize(dynamic value, String targetType, {bool growable}) {
+ static dynamic _deserialize(dynamic value, String targetType, {bool growable}) {
try {
switch (targetType) {
case 'String':
@@ -180,57 +218,68 @@ class ApiClient {
default:
Match match;
if (value is List && (match = _regList.firstMatch(targetType)) != null) {
- final newTargetType = match[1];
+ targetType = match[1]; // ignore: parameter_assignments
return value
- .map((v) => _deserialize(v, newTargetType, growable: growable))
- .toList(growable: true == growable);
+ .map((v) => _deserialize(v, targetType, growable: growable))
+ .toList(growable: growable);
}
if (value is Set && (match = _regSet.firstMatch(targetType)) != null) {
- final newTargetType = match[1];
+ targetType = match[1]; // ignore: parameter_assignments
return value
- .map((v) => _deserialize(v, newTargetType, growable: growable))
+ .map((v) => _deserialize(v, targetType, growable: growable))
.toSet();
}
if (value is Map && (match = _regMap.firstMatch(targetType)) != null) {
- final newTargetType = match[1];
+ targetType = match[1]; // ignore: parameter_assignments
return Map.fromIterables(
value.keys,
- value.values.map((v) => _deserialize(v, newTargetType, growable: growable)),
+ value.values.map((v) => _deserialize(v, targetType, growable: growable)),
);
}
break;
}
- } on Exception catch (e, stack) {
- throw ApiException.withInner(HttpStatus.internalServerError, 'Exception during deserialization.', e, stack,);
+ } catch (error, trace) {
+ throw ApiException.withInner(HttpStatus.internalServerError, 'Exception during deserialization.', error, trace,);
}
throw ApiException(HttpStatus.internalServerError, 'Could not find a suitable class for deserialization',);
}
+{{/native_serialization}}
+}
+{{#native_serialization}}
- dynamic deserialize(String json, String targetType, {bool growable}) {
- // Remove all spaces. Necessary for reg expressions as well.
- targetType = targetType.replaceAll(' ', '');
+/// Primarily intended for use in an isolate.
+class DeserializationMessage {
+ const DeserializationMessage({
+ @required this.json,
+ @required this.targetType,
+ this.growable,
+ });
+ /// The JSON value to deserialize.
+ final String json;
+
+ /// Target type to deserialize to.
+ final String targetType;
+
+ /// Whether to make deserialized lists or maps growable.
+ final bool growable;
+}
+
+/// Primarily intended for use in an isolate.
+Future deserializeAsync(DeserializationMessage message) async {
+ // Remove all spaces. Necessary for regular expressions as well.
+ final targetType = message.targetType.replaceAll(' ', '');
+
+ // If the expected target type is String, nothing to do...
return targetType == 'String'
- ? json
- : _deserialize(jsonDecode(json), targetType, growable: true == growable);
- }
+ ? message.json
+ : ApiClient._deserialize(
+ jsonDecode(message.json),
+ targetType,
+ growable: message.growable == true,
+ );
+}
{{/native_serialization}}
- String serialize(Object obj) => obj == null ? '' : json.encode(obj);
-
- /// Update query and header parameters based on authentication settings.
- /// @param authNames The authentications to apply
- void _updateParamsForAuth(
- List authNames,
- List queryParams,
- Map headerParams,
- ) {
- authNames.forEach((authName) {
- final auth = _authentications[authName];
- if (auth == null) {
- throw ArgumentError('Authentication undefined: $authName');
- }
- auth.applyToParams(queryParams, headerParams);
- });
- }
-}
+/// Primarily intended for use in an isolate.
+Future serializeAsync(Object value) async => value == null ? '' : json.encode(value);
diff --git a/modules/openapi-generator/src/main/resources/dart2/api_helper.mustache b/modules/openapi-generator/src/main/resources/dart2/api_helper.mustache
index 8e70b9920bf..92f394176f6 100644
--- a/modules/openapi-generator/src/main/resources/dart2/api_helper.mustache
+++ b/modules/openapi-generator/src/main/resources/dart2/api_helper.mustache
@@ -63,7 +63,7 @@ String parameterToString(dynamic value) {
/// Returns the decoded body as UTF-8 if the given headers indicate an 'application/json'
/// content type. Otherwise, returns the decoded body as decoded by dart:http package.
-String _decodeBodyBytes(Response response) {
+Future _decodeBodyBytes(Response response) async {
final contentType = response.headers['content-type'];
return contentType != null && contentType.toLowerCase().startsWith('application/json')
? response.bodyBytes == null ? null : utf8.decode(response.bodyBytes)
diff --git a/modules/openapi-generator/src/main/resources/dart2/apilib.mustache b/modules/openapi-generator/src/main/resources/dart2/apilib.mustache
index e17f4ed139a..df10d804011 100644
--- a/modules/openapi-generator/src/main/resources/dart2/apilib.mustache
+++ b/modules/openapi-generator/src/main/resources/dart2/apilib.mustache
@@ -7,11 +7,10 @@ import 'dart:io';
import 'package:http/http.dart';
import 'package:intl/intl.dart';
-
-import 'package:meta/meta.dart';
{{#json_serializable}}
import 'package:json_annotation/json_annotation.dart';
{{/json_serializable}}
+import 'package:meta/meta.dart';
part 'api_client.dart';
part 'api_helper.dart';
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/Dockerfile.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/Dockerfile.mustache
new file mode 100644
index 00000000000..bd60366b27f
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/Dockerfile.mustache
@@ -0,0 +1,11 @@
+FROM golang:1.16-alpine3.13 as build-env
+RUN apk add --no-cache git gcc
+RUN mkdir /app
+WORKDIR /app
+COPY . .
+RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o {{packageName}}
+FROM alpine:3.13
+COPY --from=build-env /app/{{packageName}} .
+EXPOSE 8080/tcp
+USER 1001
+ENTRYPOINT ["./{{packageName}}"]
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/README.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/README.mustache
new file mode 100644
index 00000000000..9ff2b9aeb19
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/README.mustache
@@ -0,0 +1,44 @@
+# Go Echo API Server for {{packageName}}
+
+{{#appDescriptionWithNewLines}}
+{{{appDescriptionWithNewLines}}}
+{{/appDescriptionWithNewLines}}
+
+## Overview
+This server was generated by the [openapi-generator]
+(https://openapi-generator.tech) project.
+By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub.
+-
+
+To see how to make this your own, look here:
+
+[README](https://openapi-generator.tech)
+
+- API version: {{appVersion}}{{^hideGenerationTimestamp}}
+- Build date: {{generatedDate}}{{/hideGenerationTimestamp}}
+{{#infoUrl}}
+For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
+{{/infoUrl}}
+
+### Running the server
+
+To run the server, follow these simple steps:
+
+```
+go mod download
+go build -o app
+```
+
+To run the server in a docker container
+```
+docker build --network=host -t {{{packageName}}} .
+```
+
+Once the image is built, just run
+```
+docker run --rm -it {{{packageName}}}
+```
+
+### Known Issue
+
+TBA
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/api.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/api.mustache
new file mode 100644
index 00000000000..9ac9ad29838
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/api.mustache
@@ -0,0 +1,15 @@
+package handlers
+{{#operations}}
+import (
+ "github.com/{{{gitUserId}}}/{{{gitRepoId}}}/models"
+ "github.com/labstack/echo/v4"
+ "net/http"
+){{#operation}}
+
+// {{nickname}} - {{{summary}}}
+func (c *Container) {{operationId}}(ctx echo.Context) error {
+ return ctx.JSON(http.StatusOK, models.HelloWorld {
+ Message: "Hello World",
+ })
+}
+{{/operation}}{{/operations}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/go-mod.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/go-mod.mustache
new file mode 100644
index 00000000000..4b31aa41c83
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/go-mod.mustache
@@ -0,0 +1,5 @@
+module github.com/{{{gitUserId}}}/{{{gitRepoId}}}
+
+go 1.16
+
+require github.com/labstack/echo/v4 v4.2.0
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/handler-container.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/handler-container.mustache
new file mode 100644
index 00000000000..330a32f5153
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/handler-container.mustache
@@ -0,0 +1,11 @@
+package handlers
+
+// Container will hold all dependencies for your application.
+type Container struct {
+}
+
+// NewContainer returns an empty or an initialized container for your handlers.
+func NewContainer() (Container, error) {
+ c := Container{}
+ return c, nil
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/hello-world.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/hello-world.mustache
new file mode 100644
index 00000000000..98b4d20cb61
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/hello-world.mustache
@@ -0,0 +1,6 @@
+package models
+
+// HelloWorld is a sample data structure to make sure each endpoint return something.
+type HelloWorld struct {
+ Message string `json:"message"`
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/main.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/main.mustache
new file mode 100644
index 00000000000..ef0421cdd11
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/main.mustache
@@ -0,0 +1,26 @@
+package main
+
+import (
+ "github.com/{{{gitUserId}}}/{{{gitRepoId}}}/handlers"
+ "github.com/labstack/echo/v4"
+ "github.com/labstack/echo/v4/middleware"
+)
+
+func main() {
+ e := echo.New()
+
+ //todo: handle the error!
+ c, _ := handlers.NewContainer()
+
+ // Middleware
+ e.Use(middleware.Logger())
+ e.Use(middleware.Recover())
+
+{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
+ // {{nickname}} - {{{summary}}}
+ e.{{httpMethod.toUpperCase}}("{{{basePathWithoutHost}}}{{{path}}}", c.{{operationId}})
+{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
+
+ // Start server
+ e.Logger.Fatal(e.Start(":{{serverPort}}"))
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/model.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/model.mustache
new file mode 100644
index 00000000000..ef59462f11e
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/model.mustache
@@ -0,0 +1,23 @@
+package models
+{{#models}}{{#imports}}
+{{#-first}}import (
+{{/-first}} "{{import}}"{{#-last}}
+)
+{{/-last}}{{/imports}}{{#model}}{{#isEnum}}{{#description}}// {{{classname}}} : {{{description}}}{{/description}}
+type {{{classname}}} {{^format}}{{dataType}}{{/format}}{{#format}}{{{format}}}{{/format}}
+
+// List of {{{classname}}}
+const (
+ {{#allowableValues}}
+ {{#enumVars}}
+ {{#enumClassPrefix}}{{{classname.toUpperCase}}}_{{/enumClassPrefix}}{{name}} {{{classname}}} = {{{value}}}
+ {{/enumVars}}
+ {{/allowableValues}}
+){{/isEnum}}{{^isEnum}}{{#description}}
+// {{classname}} - {{{description}}}{{/description}}
+type {{classname}} struct {
+{{#vars}}{{#description}}
+ // {{{description}}}{{/description}}
+ {{name}} {{#isNullable}}*{{/isNullable}}{{{dataType}}} `json:"{{baseName}}{{^required}},omitempty{{/required}}"{{#vendorExtensions.x-go-custom-tag}} {{{.}}}{{/vendorExtensions.x-go-custom-tag}}`
+{{/vars}}
+}{{/isEnum}}{{/model}}{{/models}}
diff --git a/modules/openapi-generator/src/main/resources/go-echo-server/openapi.mustache b/modules/openapi-generator/src/main/resources/go-echo-server/openapi.mustache
new file mode 100644
index 00000000000..51ebafb0187
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/go-echo-server/openapi.mustache
@@ -0,0 +1 @@
+{{{openapi-yaml}}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache b/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache
index 7d321a03efe..2c6b5da8b52 100644
--- a/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache
+++ b/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache
@@ -16,7 +16,7 @@ type {{classname}}Controller struct {
// New{{classname}}Controller creates a default api controller
func New{{classname}}Controller(s {{classname}}Servicer) Router {
- return &{{classname}}Controller{ service: s }
+ return &{{classname}}Controller{service: s}
}
// Routes returns all of the api route for the {{classname}}Controller
@@ -32,73 +32,128 @@ func (c *{{classname}}Controller) Routes() Routes {
}{{#operations}}{{#operation}}
// {{nickname}} - {{{summary}}}
-func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Request) { {{#hasFormParams}}
- err := r.ParseForm()
+func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Request) {
+ {{#hasFormParams}}
+ {{#isMultipart}}
+ if err := r.ParseMultipartForm(32 << 20); err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+ {{/isMultipart}}
+ {{^isMultipart}}
+ if err := r.ParseForm(); err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+ {{/isMultipart}}
+ {{/hasFormParams}}
+ {{#hasPathParams}}
+ params := mux.Vars(r)
+ {{/hasPathParams}}
+ {{#hasQueryParams}}
+ query := r.URL.Query()
+ {{/hasQueryParams}}
+ {{#allParams}}
+ {{#isPathParam}}
+ {{#isLong}}
+ {{paramName}}, err := parseInt64Parameter(params["{{baseName}}"], {{required}})
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- {{/hasFormParams}}{{#hasPathParams}}
- params := mux.Vars(r){{/hasPathParams}}{{#hasQueryParams}}
- query := r.URL.Query(){{/hasQueryParams}}{{#allParams}}{{#isPathParam}}{{#isLong}}
- {{paramName}}, err := parseInt64Parameter(params["{{baseName}}"])
- if err != nil {
- w.WriteHeader(http.StatusBadRequest)
- return
- }{{/isLong}}{{#isInteger}}
- {{paramName}}, err := parseInt32Parameter(params["{{baseName}}"])
+ {{/isLong}}
+ {{#isInteger}}
+ {{paramName}}, err := parseInt32Parameter(params["{{baseName}}"], {{required}})
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- {{/isInteger}}{{^isLong}}{{^isInteger}}
- {{paramName}} := params["{{baseName}}"]{{/isInteger}}{{/isLong}}{{/isPathParam}}{{#isQueryParam}}{{#isLong}}
- {{paramName}}, err := parseInt64Parameter(query.Get("{{baseName}}"))
+ {{/isInteger}}
+ {{^isLong}}
+ {{^isInteger}}
+ {{paramName}} := params["{{baseName}}"]
+ {{/isInteger}}{{/isLong}}
+ {{/isPathParam}}
+ {{#isQueryParam}}
+ {{#isLong}}
+ {{paramName}}, err := parseInt64Parameter(query.Get("{{baseName}}"), {{required}})
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- {{/isLong}}{{#isInteger}}
- {{paramName}}, err := parseInt32Parameter(query.Get("{{baseName}}"))
+ {{/isLong}}
+ {{#isInteger}}
+ {{paramName}}, err := parseInt32Parameter(query.Get("{{baseName}}"), {{required}})
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- {{/isInteger}}{{^isLong}}{{^isInteger}}
- {{paramName}} := {{#isArray}}strings.Split({{/isArray}}query.Get("{{baseName}}"){{#isArray}}, ","){{/isArray}}{{/isInteger}}{{/isLong}}{{/isQueryParam}}{{#isFormParam}}{{#isFile}}
- {{#isArray}}{{paramName}}, err := ReadFormFilesToTempFiles(r, "{{baseName}}"){{/isArray}}{{^isArray}}{{paramName}}, err := ReadFormFileToTempFile(r, "{{baseName}}"){{/isArray}}
+ {{/isInteger}}
+ {{#isBoolean}}
+ {{paramName}}, err := parseBoolParameter(query.Get("{{paramName}}"))
+ if err != nil {
+ w.WriteHeader(500)
+ return
+ }
+ {{/isBoolean}}
+ {{^isLong}}
+ {{^isInteger}}
+ {{^isBoolean}}
+ {{paramName}} := {{#isArray}}strings.Split({{/isArray}}query.Get("{{paramName}}"){{#isArray}}, ","){{/isArray}}
+ {{/isBoolean}}
+ {{/isInteger}}
+ {{/isLong}}
+ {{/isQueryParam}}
+ {{#isFormParam}}
+ {{#isFile}}{{#isArray}}
+ {{paramName}}, err := ReadFormFilesToTempFiles(r, "{{baseName}}"){{/isArray}}{{^isArray}}
+ {{paramName}}, err := ReadFormFileToTempFile(r, "{{baseName}}")
+ {{/isArray}}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- {{/isFile}}{{#isLong}}
- {{paramName}}, err := parseInt64Parameter( r.FormValue("{{baseName}}"))
+ {{/isFile}}
+ {{#isLong}}{{#isArray}}
+ {{paramName}}, err := parseInt64ArrayParameter(r.FormValue("{{baseName}}"), ",", {{required}}){{/isArray}}{{^isArray}}
+ {{paramName}}, err := parseInt64Parameter(r.FormValue("{{baseName}}"), {{required}}){{/isArray}}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- {{/isLong}}{{#isInteger}}
- {{paramName}}, err := parseInt32Parameter( r.FormValue("{{baseName}}"))
+ {{/isLong}}
+ {{#isInteger}}{{#isArray}}
+ {{paramName}}, err := parseInt32ArrayParameter(r.FormValue("{{baseName}}"), ",", {{required}}){{/isArray}}{{^isArray}}
+ {{paramName}}, err := parseInt32Parameter(r.FormValue("{{baseName}}"), {{required}}){{/isArray}}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- {{/isInteger}}{{^isFile}}{{^isLong}}
- {{paramName}} := r.FormValue("{{baseName}}"){{/isLong}}{{/isFile}}{{/isFormParam}}{{#isHeaderParam}}
- {{paramName}} := r.Header.Get("{{baseName}}"){{/isHeaderParam}}{{#isBodyParam}}
+ {{/isInteger}}
+ {{^isFile}}
+ {{^isLong}}
+ {{paramName}} := r.FormValue("{{baseName}}")
+ {{/isLong}}
+ {{/isFile}}
+ {{/isFormParam}}
+ {{#isHeaderParam}}
+ {{paramName}} := r.Header.Get("{{baseName}}")
+ {{/isHeaderParam}}
+ {{#isBodyParam}}
{{paramName}} := &{{dataType}}{}
if err := json.NewDecoder(r.Body).Decode(&{{paramName}}); err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
- {{/isBodyParam}}{{/allParams}}
+ {{/isBodyParam}}
+ {{/allParams}}
result, err := c.service.{{nickname}}(r.Context(){{#allParams}}, {{#isBodyParam}}*{{/isBodyParam}}{{paramName}}{{/allParams}})
- //If an error occured, encode the error with the status code
+ // If an error occurred, encode the error with the status code
if err != nil {
- EncodeJSONResponse(err.Error(), &result.Code, w)
+ EncodeJSONResponse(err.Error(), &result.Code,{{#addResponseHeaders}} result.Headers,{{/addResponseHeaders}} w)
return
}
- //If no error, encode the body and the result code
- EncodeJSONResponse(result.Body, &result.Code, w)
-
+ // If no error, encode the body and the result code
+ EncodeJSONResponse(result.Body, &result.Code,{{#addResponseHeaders}} result.Headers,{{/addResponseHeaders}} w)
+
}{{/operation}}{{/operations}}
diff --git a/modules/openapi-generator/src/main/resources/go-server/helpers.mustache b/modules/openapi-generator/src/main/resources/go-server/helpers.mustache
index 2441678ab3b..13115656bc0 100644
--- a/modules/openapi-generator/src/main/resources/go-server/helpers.mustache
+++ b/modules/openapi-generator/src/main/resources/go-server/helpers.mustache
@@ -3,6 +3,22 @@ package {{packageName}}
//Response return a ImplResponse struct filled
func Response(code int, body interface{}) ImplResponse {
- return ImplResponse{Code: code, Body: body}
+ return ImplResponse {
+ Code: code,
+ {{#addResponseHeaders}}
+ Headers: nil,
+ {{/addResponseHeaders}}
+ Body: body,
+ }
}
+{{#addResponseHeaders}}
+//ResponseWithHeaders return a ImplResponse struct filled, including headers
+func ResponseWithHeaders(code int, headers map[string][]string, body interface{}) ImplResponse {
+ return ImplResponse {
+ Code: code,
+ Headers: headers,
+ Body: body,
+ }
+}
+{{/addResponseHeaders}}
diff --git a/modules/openapi-generator/src/main/resources/go-server/impl.mustache b/modules/openapi-generator/src/main/resources/go-server/impl.mustache
index 3333cdecdc2..48d5a3e5e5c 100644
--- a/modules/openapi-generator/src/main/resources/go-server/impl.mustache
+++ b/modules/openapi-generator/src/main/resources/go-server/impl.mustache
@@ -4,5 +4,8 @@ package {{packageName}}
//Implementation response defines an error code with the associated body
type ImplResponse struct {
Code int
+ {{#addResponseHeaders}}
+ Headers map[string][]string
+ {{/addResponseHeaders}}
Body interface{}
-}
\ No newline at end of file
+}
diff --git a/modules/openapi-generator/src/main/resources/go-server/routers.mustache b/modules/openapi-generator/src/main/resources/go-server/routers.mustache
index 6338eecd2e5..d76397166c6 100644
--- a/modules/openapi-generator/src/main/resources/go-server/routers.mustache
+++ b/modules/openapi-generator/src/main/resources/go-server/routers.mustache
@@ -3,22 +3,24 @@ package {{packageName}}
import (
"encoding/json"
+ "errors"
+ "github.com/gorilla/mux"
+ {{#featureCORS}}
+ "github.com/gorilla/handlers"
+ {{/featureCORS}}
"io/ioutil"
"mime/multipart"
"net/http"
"os"
"strconv"
- {{#featureCORS}}
- "github.com/gorilla/handlers"
- {{/featureCORS}}
- "github.com/gorilla/mux"
+ "strings"
)
// A Route defines the parameters for an api endpoint
type Route struct {
- Name string
- Method string
- Pattern string
+ Name string
+ Method string
+ Pattern string
HandlerFunc http.HandlerFunc
}
@@ -30,6 +32,8 @@ type Router interface {
Routes() Routes
}
+const errMsgRequiredMissing = "required parameter is missing"
+
// NewRouter creates a new router for any number of api routers
func NewRouter(routers ...Router) *mux.Router {
router := mux.NewRouter().StrictSlash(true)
@@ -54,8 +58,21 @@ func NewRouter(routers ...Router) *mux.Router {
}
// EncodeJSONResponse uses the json encoder to write an interface to the http response with an optional status code
-func EncodeJSONResponse(i interface{}, status *int, w http.ResponseWriter) error {
+func EncodeJSONResponse(i interface{}, status *int,{{#addResponseHeaders}} headers map[string][]string,{{/addResponseHeaders}} w http.ResponseWriter) error {
+ {{#addResponseHeader}}
+ wHeader := w.Header()
+ if headers != nil {
+ for key, values := range headers {
+ for _, value := range values {
+ wHeader.Add(key, value)
+ }
+ }
+ }
+ wHeader.Set("Content-Type", "application/json; charset=UTF-8")
+ {{/addResponseHeader}}
+ {{^addResponseHeader}}
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
+ {{/addResponseHeader}}
if status != nil {
w.WriteHeader(*status)
} else {
@@ -121,17 +138,91 @@ func readFileHeaderToTempFile(fileHeader *multipart.FileHeader) (*os.File, error
return file, nil
}
+// parseInt64Parameter parses a string parameter to an int64.
+func parseInt64Parameter(param string, required bool) (int64, error) {
+ if param == "" {
+ if required {
+ return 0, errors.New(errMsgRequiredMissing)
+ }
+
+ return 0, nil
+ }
-// parseInt64Parameter parses a sting parameter to an int64
-func parseInt64Parameter(param string) (int64, error) {
return strconv.ParseInt(param, 10, 64)
}
-// parseInt32Parameter parses a sting parameter to an int32
-func parseInt32Parameter(param string) (int32, error) {
+// parseInt32Parameter parses a string parameter to an int32.
+func parseInt32Parameter(param string, required bool) (int32, error) {
+ if param == "" {
+ if required {
+ return 0, errors.New(errMsgRequiredMissing)
+ }
+
+ return 0, nil
+ }
+
val, err := strconv.ParseInt(param, 10, 32)
if err != nil {
return -1, err
}
+
return int32(val), nil
}
+
+// parseBoolParameter parses a string parameter to a bool
+func parseBoolParameter(param string) (bool, error) {
+ val, err := strconv.ParseBool(param)
+ if err != nil {
+ return false, err
+ }
+
+ return bool(val), nil
+}
+
+// parseInt64ArrayParameter parses a string parameter containing array of values to []int64.
+func parseInt64ArrayParameter(param, delim string, required bool) ([]int64, error) {
+ if param == "" {
+ if required {
+ return nil, errors.New(errMsgRequiredMissing)
+ }
+
+ return nil, nil
+ }
+
+ str := strings.Split(param, delim)
+ ints := make([]int64, len(str))
+
+ for i, s := range str {
+ if v, err := strconv.ParseInt(s, 10, 64); err != nil {
+ return nil, err
+ } else {
+ ints[i] = v
+ }
+ }
+
+ return ints, nil
+}
+
+// parseInt32ArrayParameter parses a string parameter containing array of values to []int32.
+func parseInt32ArrayParameter(param, delim string, required bool) ([]int32, error) {
+ if param == "" {
+ if required {
+ return nil, errors.New(errMsgRequiredMissing)
+ }
+
+ return nil, nil
+ }
+
+ str := strings.Split(param, delim)
+ ints := make([]int32, len(str))
+
+ for i, s := range str {
+ if v, err := strconv.ParseInt(s, 10, 32); err != nil {
+ return nil, err
+ } else {
+ ints[i] = int32(v)
+ }
+ }
+
+ return ints, nil
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/go/client.mustache b/modules/openapi-generator/src/main/resources/go/client.mustache
index a68fa9ee1dd..476a2081f88 100644
--- a/modules/openapi-generator/src/main/resources/go/client.mustache
+++ b/modules/openapi-generator/src/main/resources/go/client.mustache
@@ -112,7 +112,7 @@ func selectHeaderAccept(accepts []string) string {
return strings.Join(accepts, ",")
}
-// contains is a case insenstive match, finding needle in a haystack
+// contains is a case insensitive match, finding needle in a haystack
func contains(haystack []string, needle string) bool {
for _, a := range haystack {
if strings.ToLower(a) == strings.ToLower(needle) {
diff --git a/modules/openapi-generator/src/main/resources/go/model_enum.mustache b/modules/openapi-generator/src/main/resources/go/model_enum.mustache
index 1d3c2244c09..11dfbfc7d33 100644
--- a/modules/openapi-generator/src/main/resources/go/model_enum.mustache
+++ b/modules/openapi-generator/src/main/resources/go/model_enum.mustache
@@ -12,6 +12,14 @@ const (
{{/allowableValues}}
)
+var allowed{{{classname}}}EnumValues = []{{{classname}}}{
+ {{#allowableValues}}
+ {{#enumVars}}
+ {{{value}}},
+ {{/enumVars}}
+ {{/allowableValues}}
+}
+
func (v *{{{classname}}}) UnmarshalJSON(src []byte) error {
var value {{^format}}{{dataType}}{{/format}}{{#format}}{{{format}}}{{/format}}
err := json.Unmarshal(src, &value)
@@ -19,7 +27,7 @@ func (v *{{{classname}}}) UnmarshalJSON(src []byte) error {
return err
}
enumTypeValue := {{{classname}}}(value)
- for _, existing := range []{{classname}}{ {{#allowableValues}}{{#enumVars}}{{{value}}}, {{/enumVars}} {{/allowableValues}} } {
+ for _, existing := range allowed{{{classname}}}EnumValues {
if existing == enumTypeValue {
*v = enumTypeValue
return nil
@@ -29,6 +37,27 @@ func (v *{{{classname}}}) UnmarshalJSON(src []byte) error {
return fmt.Errorf("%+v is not a valid {{classname}}", value)
}
+// New{{{classname}}}FromValue returns a pointer to a valid {{{classname}}}
+// for the value passed as argument, or an error if the value passed is not allowed by the enum
+func New{{{classname}}}FromValue(v {{^format}}{{dataType}}{{/format}}{{#format}}{{{format}}}{{/format}}) (*{{{classname}}}, error) {
+ ev := {{{classname}}}(v)
+ if ev.IsValid() {
+ return &ev, nil
+ } else {
+ return nil, fmt.Errorf("invalid value '%v' for {{{classname}}}: valid values are %v", v, allowed{{{classname}}}EnumValues)
+ }
+}
+
+// IsValid return true if the value is valid for the enum, false otherwise
+func (v {{{classname}}}) IsValid() bool {
+ for _, existing := range allowed{{{classname}}}EnumValues {
+ if existing == v {
+ return true
+ }
+ }
+ return false
+}
+
// Ptr returns reference to {{{name}}} value
func (v {{{classname}}}) Ptr() *{{{classname}}} {
return &v
diff --git a/modules/openapi-generator/src/main/resources/go/response.mustache b/modules/openapi-generator/src/main/resources/go/response.mustache
index 1a8765bae8f..4691e8f428f 100644
--- a/modules/openapi-generator/src/main/resources/go/response.mustache
+++ b/modules/openapi-generator/src/main/resources/go/response.mustache
@@ -23,7 +23,7 @@ type APIResponse struct {
Payload []byte `json:"-"`
}
-// NewAPIResponse returns a new APIResonse object.
+// NewAPIResponse returns a new APIResponse object.
func NewAPIResponse(r *http.Response) *APIResponse {
response := &APIResponse{Response: r}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/build.gradle.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/build.gradle.mustache
index 415a8c25574..1f58112db53 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/build.gradle.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/build.gradle.mustache
@@ -114,3 +114,11 @@ dependencies {
{{/jvm-retrofit2}}
testCompile "io.kotlintest:kotlintest-runner-junit5:3.4.2"
}
+{{#kotlinx_serialization}}
+
+tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
+ kotlinOptions {
+ freeCompilerArgs += "-Xopt-in=kotlinx.serialization.ExperimentalSerializationApi"
+ }
+}
+{{/kotlinx_serialization}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/data_class.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/data_class.mustache
index b83b7aff952..117cdef8fd7 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/data_class.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/data_class.mustache
@@ -70,6 +70,9 @@ import java.io.Serializable
* {{{description}}}
* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}}
*/
+ {{#kotlinx_serialization}}
+ @KSerializable
+ {{/kotlinx_serialization}}
{{#nonPublicApi}}internal {{/nonPublicApi}}enum class {{{nameInCamelCase}}}(val value: {{^isContainer}}{{dataType}}{{/isContainer}}{{#isContainer}}kotlin.String{{/isContainer}}) {
{{#allowableValues}}
{{#enumVars}}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigDecimalAdapter.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigDecimalAdapter.kt.mustache
index 5efc613a20e..609d15a34d3 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigDecimalAdapter.kt.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigDecimalAdapter.kt.mustache
@@ -1,5 +1,6 @@
package {{packageName}}.infrastructure
+{{#kotlinx_serialization}}
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializer
import kotlinx.serialization.encoding.Decoder
@@ -7,13 +8,26 @@ import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.SerialDescriptor
+{{/kotlinx_serialization}}
+{{#moshi}}
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+{{/moshi}}
import java.math.BigDecimal
-@Serializer(forClass = BigDecimal::class)
+{{#kotlinx_serialization}}@Serializer(forClass = BigDecimal::class)
object BigDecimalAdapter : KSerializer {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigDecimal", PrimitiveKind.STRING)
-
override fun deserialize(decoder: Decoder): BigDecimal = BigDecimal(decoder.decodeString())
-
override fun serialize(encoder: Encoder, value: BigDecimal) = encoder.encodeString(value.toPlainString())
-}
\ No newline at end of file
+}{{/kotlinx_serialization}}{{#moshi}}{{#nonPublicApi}}internal {{/nonPublicApi}}class BigDecimalAdapter {
+ @ToJson
+ fun toJson(value: BigDecimal): String {
+ return value.toPlainString()
+ }
+
+ @FromJson
+ fun fromJson(value: String): BigDecimal {
+ return BigDecimal(value)
+ }
+}{{/moshi}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigIntegerAdapter.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigIntegerAdapter.kt.mustache
index bd2b4d3c8e9..2924e8f63a2 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigIntegerAdapter.kt.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/BigIntegerAdapter.kt.mustache
@@ -1,5 +1,6 @@
package {{packageName}}.infrastructure
+{{#kotlinx_serialization}}
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializer
import kotlinx.serialization.encoding.Decoder
@@ -7,12 +8,16 @@ import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.SerialDescriptor
+{{/kotlinx_serialization}}
+{{#moshi}}
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+{{/moshi}}
import java.math.BigInteger
-@Serializer(forClass = BigInteger::class)
+{{#kotlinx_serialization}}@Serializer(forClass = BigInteger::class)
object BigIntegerAdapter : KSerializer {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigInteger", PrimitiveKind.STRING)
-
override fun deserialize(decoder: Decoder): BigInteger {
return BigInteger(decoder.decodeString())
}
@@ -20,4 +25,14 @@ object BigIntegerAdapter : KSerializer {
override fun serialize(encoder: Encoder, value: BigInteger) {
encoder.encodeString(value.toString())
}
-}
\ No newline at end of file
+}{{/kotlinx_serialization}}{{#moshi}}{{#nonPublicApi}}internal {{/nonPublicApi}}class BigIntegerAdapter {
+ @ToJson
+ fun toJson(value: BigInteger): String {
+ return value.toString()
+ }
+
+ @FromJson
+ fun fromJson(value: String): BigInteger {
+ return BigInteger(value)
+ }
+}{{/moshi}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/Serializer.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/Serializer.kt.mustache
index e9ed019095e..beef3fc2bf3 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/Serializer.kt.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/Serializer.kt.mustache
@@ -63,6 +63,8 @@ import java.util.concurrent.atomic.AtomicLong
{{^moshiCodeGen}}
.add(KotlinJsonAdapterFactory())
{{/moshiCodeGen}}
+ .add(BigDecimalAdapter())
+ .add(BigIntegerAdapter())
@JvmStatic
val moshi: Moshi by lazy {
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache
index 0d834b1e55c..aa5a275a9f3 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/infrastructure/ApiClient.kt.mustache
@@ -25,7 +25,10 @@ import okhttp3.Request
import okhttp3.Headers
import okhttp3.MultipartBody
import java.io.File
+import java.io.BufferedWriter
+import java.io.FileWriter
import java.net.URLConnection
+import java.nio.file.Files
import java.util.Date
{{^threetenbp}}
import java.time.LocalDate
@@ -171,6 +174,15 @@ import org.threeten.bp.OffsetTime
if (bodyContent.isEmpty()) {
return null
}
+ if (T::class.java == File::class.java) {
+ // return tempfile
+ val f = Files.createTempFile("tmp.{{packageName}}", null).toFile()
+ f.deleteOnExit()
+ val out = BufferedWriter(FileWriter(f))
+ out.write(bodyContent)
+ out.close()
+ return f as T
+ }
return when(mediaType) {
JsonMediaType -> {{#moshi}}Serializer.moshi.adapter(T::class.java).fromJson(bodyContent){{/moshi}}{{#gson}}Serializer.gson.fromJson(bodyContent, T::class.java){{/gson}}{{#jackson}}Serializer.jacksonObjectMapper.readValue(bodyContent, T::class.java){{/jackson}}
else -> throw UnsupportedOperationException("responseBody currently only supports JSON body.")
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/api.mustache
index 07bf4667f39..bca56e88bae 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/api.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/api.mustache
@@ -47,6 +47,12 @@ import okhttp3.MultipartBody
{{/isMultipart}}
{{/x-kotlin-multipart-import}}
+{{#operation}}
+{{#isResponseFile}}
+import okhttp3.ResponseBody
+
+{{/isResponseFile}}
+{{/operation}}
interface {{classname}} {
{{#operation}}
/**
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/formParams.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/formParams.mustache
index d5267aa7746..041cad11529 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/formParams.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/formParams.mustache
@@ -1 +1 @@
-{{#isFormParam}}{{^isFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}}("{{baseName}}") {{{paramName}}}: {{{dataType}}}{{/isFile}}{{#isFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field("{{baseName}}"){{/isMultipart}} {{{paramName}}}: MultipartBody.Part{{/isFile}}{{/isFormParam}}
\ No newline at end of file
+{{#isFormParam}}{{^isFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}}("{{baseName}}") {{{paramName}}}: {{{dataType}}}{{#required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}}{{^required}}?{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{^defaultValue}} = null{{/defaultValue}}{{/required}}{{/isFile}}{{#isFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field("{{baseName}}"){{/isMultipart}} {{{paramName}}}: MultipartBody.Part{{^required}}? = null{{/required}}{{/isFile}}{{/isFormParam}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/infrastructure/ApiClient.kt.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/infrastructure/ApiClient.kt.mustache
index 66e77122a81..ea19748fbfb 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/infrastructure/ApiClient.kt.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/infrastructure/ApiClient.kt.mustache
@@ -25,6 +25,7 @@ import okhttp3.Interceptor
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import okhttp3.logging.HttpLoggingInterceptor
+import retrofit2.Converter
import retrofit2.converter.scalars.ScalarsConverterFactory
{{#useRxJava}}
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory
@@ -55,7 +56,8 @@ import okhttp3.MediaType.Companion.toMediaType
private var baseUrl: String = defaultBasePath,
private val okHttpClientBuilder: OkHttpClient.Builder? = null{{^kotlinx_serialization}},
private val serializerBuilder: {{#gson}}Gson{{/gson}}{{#moshi}}Moshi.{{/moshi}}Builder = Serializer.{{#gson}}gson{{/gson}}{{#moshi}}moshi{{/moshi}}Builder{{/kotlinx_serialization}},
- private val okHttpClient : OkHttpClient? = null
+ private val okHttpClient : OkHttpClient? = null,
+ private val converterFactory: Converter.Factory? = null,
) {
private val apiAuthorizations = mutableMapOf()
var logger: ((String) -> Unit)? = null
@@ -81,6 +83,11 @@ import okhttp3.MediaType.Companion.toMediaType
{{#kotlinx_serialization}}
.addConverterFactory(jvmJson.asConverterFactory("application/json".toMediaType()))
{{/kotlinx_serialization}}
+ .apply {
+ if (converterFactory != null) {
+ addConverterFactory(converterFactory)
+ }
+ }
}
private val clientBuilder: OkHttpClient.Builder by lazy {
diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/apiDelegate.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/apiDelegate.mustache
index d45f9f79f2e..bbf57f85b7b 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/apiDelegate.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/apiDelegate.mustache
@@ -8,6 +8,7 @@ import org.springframework.http.ResponseEntity
import org.springframework.web.context.request.NativeWebRequest
import org.springframework.core.io.Resource
{{#reactive}}
+import kotlinx.coroutines.flow.Flow
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
@@ -32,7 +33,7 @@ interface {{classname}}Delegate {
/**
* @see {{classname}}#{{operationId}}
*/
- fun {{operationId}}({{#allParams}}{{paramName}}: {{^isFile}}{{>optionalDataType}}{{/isFile}}{{#isFile}}Resource?{{/isFile}}{{^-last}},
+ {{#reactive}}{{^isArray}}suspend {{/isArray}}{{/reactive}}fun {{operationId}}({{#allParams}}{{paramName}}: {{^isFile}}{{>optionalDataType}}{{/isFile}}{{#isFile}}Resource?{{/isFile}}{{^-last}},
{{/-last}}{{/allParams}}): {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {
{{>methodBody}}
}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/apiInterface.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/apiInterface.mustache
index bc224b50080..5e9b3888c8d 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/apiInterface.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/apiInterface.mustache
@@ -83,7 +83,7 @@ interface {{classname}} {
return {{>returnValue}}
{{/isDelegate}}
{{#isDelegate}}
- return getDelegate().{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}});
+ return getDelegate().{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
{{/isDelegate}}
}
{{/operation}}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/enumClass.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/enumClass.mustache
index 2f24a1de76b..bd0794c7f12 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/enumClass.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/enumClass.mustache
@@ -4,6 +4,6 @@
*/
enum class {{classname}}(val value: {{dataType}}) {
{{#allowableValues}}{{#enumVars}}
- {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
+ @JsonProperty({{{value}}}) {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
{{/enumVars}}{{/allowableValues}}
}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/methodBody.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/methodBody.mustache
index 69a9fd42d93..3e3b63e9ab0 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-spring/methodBody.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-spring/methodBody.mustache
@@ -1,3 +1,4 @@
+{{^reactive}}
{{#examples}}
{{#-first}}
{{#async}}
@@ -21,3 +22,7 @@ return CompletableFuture.supplyAsync(()-> {
{{^examples}}
return {{#async}}CompletableFuture.completedFuture({{/async}}ResponseEntity({{#returnSuccessCode}}HttpStatus.OK{{/returnSuccessCode}}{{^returnSuccessCode}}HttpStatus.NOT_IMPLEMENTED{{/returnSuccessCode}})
{{/examples}}
+{{/reactive}}
+{{#reactive}}
+return ResponseEntity({{#returnSuccessCode}}HttpStatus.OK{{/returnSuccessCode}}{{^returnSuccessCode}}HttpStatus.NOT_IMPLEMENTED{{/returnSuccessCode}})
+{{/reactive}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/php-symfony/model_variables.mustache b/modules/openapi-generator/src/main/resources/php-symfony/model_variables.mustache
index 3ef46d1c9b0..d79a5feb74a 100644
--- a/modules/openapi-generator/src/main/resources/php-symfony/model_variables.mustache
+++ b/modules/openapi-generator/src/main/resources/php-symfony/model_variables.mustache
@@ -7,6 +7,9 @@
* @SerializedName("{{baseName}}")
{{#required}}
* @Assert\NotNull()
+ {{^isPrimitiveType}}
+ * @Assert\Valid()
+ {{/isPrimitiveType}}
{{/required}}
{{#isEnum}}
{{#isContainer}}
diff --git a/modules/openapi-generator/src/main/resources/php/model_generic.mustache b/modules/openapi-generator/src/main/resources/php/model_generic.mustache
index 276b2bd9d8c..64bb657af16 100644
--- a/modules/openapi-generator/src/main/resources/php/model_generic.mustache
+++ b/modules/openapi-generator/src/main/resources/php/model_generic.mustache
@@ -188,12 +188,12 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}}{{/parentSchema}}{{^par
*/
public function listInvalidProperties()
{
- {{#parent}}
+ {{#parentSchema}}
$invalidProperties = parent::listInvalidProperties();
- {{/parent}}
- {{^parent}}
+ {{/parentSchema}}
+ {{^parentSchema}}
$invalidProperties = [];
- {{/parent}}
+ {{/parentSchema}}
{{#vars}}
{{#required}}
diff --git a/modules/openapi-generator/src/main/resources/powershell/api_doc.mustache b/modules/openapi-generator/src/main/resources/powershell/api_doc.mustache
index c892573091e..7903ec98afe 100644
--- a/modules/openapi-generator/src/main/resources/powershell/api_doc.mustache
+++ b/modules/openapi-generator/src/main/resources/powershell/api_doc.mustache
@@ -78,8 +78,8 @@ Name | Type | Description | Notes
{{/allParams}}
### Return type
-# cmdlet returns PSCustomObject, the return object contains the properties of below type
-{{#returnType}}{{#returnTypeIsPrimitive}}**{{{returnType}}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{{returnType}}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}void (empty response body){{/returnType}}
+
+{{#returnType}}{{#returnTypeIsPrimitive}}**{{{returnType}}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{{returnType}}}**]({{returnBaseType}}.md) (PSCustomObject){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}void (empty response body){{/returnType}}
### Authorization
diff --git a/modules/openapi-generator/src/main/resources/powershell/appveyor.mustache b/modules/openapi-generator/src/main/resources/powershell/appveyor.mustache
index bf3770e187a..d1047879e53 100644
--- a/modules/openapi-generator/src/main/resources/powershell/appveyor.mustache
+++ b/modules/openapi-generator/src/main/resources/powershell/appveyor.mustache
@@ -1,24 +1,26 @@
{{> partial_header}}
version: 1.0.{build}
image:
- - Visual Studio 2019 # PS 6.x
- #- Visual Studio 2017 # PS 5.x
- #- Ubuntu # PS 6.x
- # ref: https://www.appveyor.com/docs/build-environment/#build-worker-images
+ - Visual Studio 2019 # PWSH 7.x
+ #- Visual Studio 2017 # PS 5.x, PWSH 6.x
+ #- Ubuntu # PWSH 6.x
+ # ref: https://www.appveyor.com/docs/windows-images-software/
install:
- - ps: $PSVersionTable.PSVersion
- - ps: Install-Module Pester -Force -Scope CurrentUser
+ - pwsh: $PSVersionTable.PSVersion
+ - pwsh: Install-Module Pester -Force -Scope CurrentUser
build: off
test_script:
- - ps: |
+ - pwsh: |
+ .\Build.ps1
+ Import-Module -Name '.\src\{{{packageName}}}'
$Result = Invoke-Pester -PassThru
if ($Result.FailedCount -gt 0) {
$host.SetShouldExit($Result.FailedCount)
exit $Result.FailedCount
}
deploy_script:
- - ps: |
- if ($env:APPVEYOR_REPO_TAG -eq $true -and $env:NuGetApiKey -ne $null -and $env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019") {
+ - pwsh: |
+ if ($env:APPVEYOR_REPO_TAG -eq $true -and $env:NuGetApiKey -ne $null) {
.\Build.ps1
try {
Publish-Module -NuGetApiKey $env:NuGetApiKey -Path .\src\{{{packageName}}}\ -Confirm:$False -Verbose
diff --git a/modules/openapi-generator/src/main/resources/python/api.mustache b/modules/openapi-generator/src/main/resources/python/api.mustache
index cbad6df2c54..37339fc5115 100644
--- a/modules/openapi-generator/src/main/resources/python/api.mustache
+++ b/modules/openapi-generator/src/main/resources/python/api.mustache
@@ -230,8 +230,8 @@ class {{classname}}(object):
'min_length': {{minLength}},{{/minLength}}{{#maxItems}}
'max_items': {{maxItems}},{{/maxItems}}{{#minItems}}
'min_items': {{minItems}},{{/minItems}}{{#maximum}}
- {{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}},{{/maximum}}{{#minimum}}
- {{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}},{{/minimum}}{{#pattern}}
+ {{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}{{^exclusiveMaximum}}'inclusive_maximum'{{/exclusiveMaximum}}: {{maximum}},{{/maximum}}{{#minimum}}
+ {{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}{{^exclusiveMinimum}}'inclusive_minimum'{{/exclusiveMinimum}}: {{minimum}},{{/minimum}}{{#pattern}}
'regex': {
'pattern': r'{{{vendorExtensions.x-regex}}}', # noqa: E501{{#vendorExtensions.x-modifiers}}
{{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}}
diff --git a/modules/openapi-generator/src/main/resources/python/model_doc.mustache b/modules/openapi-generator/src/main/resources/python/model_doc.mustache
index ff7358618ea..3f7c8263df2 100644
--- a/modules/openapi-generator/src/main/resources/python/model_doc.mustache
+++ b/modules/openapi-generator/src/main/resources/python/model_doc.mustache
@@ -28,9 +28,9 @@ Name | Type | Description | Notes
{{#optionalVars}}
**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}.md){{/complexType}} | {{description}} | [optional] {{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}}
{{/optionalVars}}
-{{#additionalPropertiesType}}
-**any string name** | **{{additionalPropertiesType}}** | any string name can be used but the value must be the correct type | [optional]
-{{/additionalPropertiesType}}
+{{#additionalProperties}}
+**any string name** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}.md){{/complexType}} | any string name can be used but the value must be the correct type | [optional]
+{{/additionalProperties}}
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
diff --git a/modules/openapi-generator/src/main/resources/python/model_templates/classvars.mustache b/modules/openapi-generator/src/main/resources/python/model_templates/classvars.mustache
index 88ae5df9f12..0e5ff25b97f 100644
--- a/modules/openapi-generator/src/main/resources/python/model_templates/classvars.mustache
+++ b/modules/openapi-generator/src/main/resources/python/model_templates/classvars.mustache
@@ -60,7 +60,7 @@
{{/optionalVars}}
}
-{{#additionalPropertiesType}}
+{{#additionalProperties}}
@cached_property
def additional_properties_type():
"""
@@ -72,11 +72,11 @@
lazy_import()
{{/-first}}
{{/imports}}
- return ({{{additionalPropertiesType}}},) # noqa: E501
-{{/additionalPropertiesType}}
-{{^additionalPropertiesType}}
+ return ({{{dataType}}},) # noqa: E501
+{{/additionalProperties}}
+{{^additionalProperties}}
additional_properties_type = None
-{{/additionalPropertiesType}}
+{{/additionalProperties}}
_nullable = {{#isNullable}}True{{/isNullable}}{{^isNullable}}False{{/isNullable}}
diff --git a/modules/openapi-generator/src/main/resources/python/model_templates/method_init_composed.mustache b/modules/openapi-generator/src/main/resources/python/model_templates/method_init_composed.mustache
index 9b298379710..ca0505ead96 100644
--- a/modules/openapi-generator/src/main/resources/python/model_templates/method_init_composed.mustache
+++ b/modules/openapi-generator/src/main/resources/python/model_templates/method_init_composed.mustache
@@ -10,7 +10,52 @@
'_additional_properties_model_instances',
])
-{{> model_templates/method_init_shared }}
+ @convert_js_args_to_python_args
+ def __init__(self, *args, **kwargs): # noqa: E501
+ """{{classname}} - a model defined in OpenAPI
+
+ Keyword Args:
+{{#requiredVars}}
+{{#defaultValue}}
+ {{name}} ({{{dataType}}}):{{#description}} {{{description}}}.{{/description}} defaults to {{{defaultValue}}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501
+{{/defaultValue}}
+{{^defaultValue}}
+ {{name}} ({{{dataType}}}):{{#description}} {{{description}}}{{/description}}
+{{/defaultValue}}
+{{/requiredVars}}
+{{> model_templates/docstring_init_required_kwargs }}
+{{#optionalVars}}
+ {{name}} ({{{dataType}}}):{{#description}} {{{description}}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501
+{{/optionalVars}}
+ """
+
+{{#requiredVars}}
+{{#defaultValue}}
+ {{name}} = kwargs.get('{{name}}', {{{defaultValue}}})
+{{/defaultValue}}
+{{/requiredVars}}
+ _check_type = kwargs.pop('_check_type', True)
+ _spec_property_naming = kwargs.pop('_spec_property_naming', False)
+ _path_to_item = kwargs.pop('_path_to_item', ())
+ _configuration = kwargs.pop('_configuration', None)
+ _visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
+
+ if args:
+ raise ApiTypeError(
+ "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
+ args,
+ self.__class__.__name__,
+ ),
+ path_to_item=_path_to_item,
+ valid_classes=(self.__class__,),
+ )
+
+ self._data_store = {}
+ self._check_type = _check_type
+ self._spec_property_naming = _spec_property_naming
+ self._path_to_item = _path_to_item
+ self._configuration = _configuration
+ self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
constant_args = {
'_check_type': _check_type,
@@ -19,28 +64,18 @@
'_configuration': _configuration,
'_visited_composed_classes': self._visited_composed_classes,
}
- required_args = {
-{{#requiredVars}}
- '{{name}}': {{name}},
-{{/requiredVars}}
- }
- model_args = {}
- model_args.update(required_args)
- model_args.update(kwargs)
composed_info = validate_get_composed_info(
- constant_args, model_args, self)
+ constant_args, kwargs, self)
self._composed_instances = composed_info[0]
self._var_name_to_model_instances = composed_info[1]
self._additional_properties_model_instances = composed_info[2]
- unused_args = composed_info[3]
+ discarded_args = composed_info[3]
- for var_name, var_value in required_args.items():
- setattr(self, var_name, var_value)
for var_name, var_value in kwargs.items():
- if var_name in unused_args and \
+ if var_name in discarded_args and \
self._configuration is not None and \
self._configuration.discard_unknown_keys and \
- not self._additional_properties_model_instances:
+ self._additional_properties_model_instances:
# discard variable.
continue
setattr(self, var_name, var_value)
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/python/model_templates/methods_setattr_getattr_composed.mustache b/modules/openapi-generator/src/main/resources/python/model_templates/methods_setattr_getattr_composed.mustache
index 6b1013ca997..de7887ebdbd 100644
--- a/modules/openapi-generator/src/main/resources/python/model_templates/methods_setattr_getattr_composed.mustache
+++ b/modules/openapi-generator/src/main/resources/python/model_templates/methods_setattr_getattr_composed.mustache
@@ -4,27 +4,43 @@
self.__dict__[name] = value
return
- # set the attribute on the correct instance
- model_instances = self._var_name_to_model_instances.get(
- name, self._additional_properties_model_instances)
- if model_instances:
- for model_instance in model_instances:
- if model_instance == self:
- self.set_attribute(name, value)
- else:
- setattr(model_instance, name, value)
- if name not in self._var_name_to_model_instances:
- # we assigned an additional property
- self.__dict__['_var_name_to_model_instances'][name] = (
- model_instance
- )
- return None
+ """
+ Use cases:
+ 1. additional_properties_type is None (additionalProperties == False in spec)
+ Check for property presence in self.openapi_types
+ if not present then throw an error
+ if present set in self, set attribute
+ always set on composed schemas
+ 2. additional_properties_type exists
+ set attribute on self
+ always set on composed schemas
+ """
+ if self.additional_properties_type is None:
+ """
+ For an attribute to exist on a composed schema it must:
+ - fulfill schema_requirements in the self composed schema not considering oneOf/anyOf/allOf schemas AND
+ - fulfill schema_requirements in each oneOf/anyOf/allOf schemas
- raise ApiAttributeError(
- "{0} has no attribute '{1}'".format(
- type(self).__name__, name),
- [e for e in [self._path_to_item, name] if e]
- )
+ schema_requirements:
+ For an attribute to exist on a schema it must:
+ - be present in properties at the schema OR
+ - have additionalProperties unset (defaults additionalProperties = any type) OR
+ - have additionalProperties set
+ """
+ if name not in self.openapi_types:
+ raise ApiAttributeError(
+ "{0} has no attribute '{1}'".format(
+ type(self).__name__, name),
+ [e for e in [self._path_to_item, name] if e]
+ )
+ # attribute must be set on self and composed instances
+ self.set_attribute(name, value)
+ for model_instance in self._composed_instances:
+ setattr(model_instance, name, value)
+ if name not in self._var_name_to_model_instances:
+ # we assigned an additional property
+ self.__dict__['_var_name_to_model_instances'][name] = self._composed_instances + [self]
+ return None
__unset_attribute_value__ = object()
@@ -34,13 +50,12 @@
return self.__dict__[name]
# get the attribute from the correct instance
- model_instances = self._var_name_to_model_instances.get(
- name, self._additional_properties_model_instances)
+ model_instances = self._var_name_to_model_instances.get(name)
values = []
- # A composed model stores child (oneof/anyOf/allOf) models under
- # self._var_name_to_model_instances. A named property can exist in
- # multiple child models. If the property is present in more than one
- # child model, the value must be the same across all the child models.
+ # A composed model stores self and child (oneof/anyOf/allOf) models under
+ # self._var_name_to_model_instances.
+ # Any property must exist in self and all model instances
+ # The value stored in all model instances must be the same
if model_instances:
for model_instance in model_instances:
if name in model_instance._data_store:
diff --git a/modules/openapi-generator/src/main/resources/python/model_utils.mustache b/modules/openapi-generator/src/main/resources/python/model_utils.mustache
index 07b77a99d18..3621a5eec51 100644
--- a/modules/openapi-generator/src/main/resources/python/model_utils.mustache
+++ b/modules/openapi-generator/src/main/resources/python/model_utils.mustache
@@ -1211,13 +1211,19 @@ def model_to_dict(model_instance, serialize=True):
# exist in attribute_map
attr = model_instance.attribute_map.get(attr, attr)
if isinstance(value, list):
- if not value or isinstance(value[0], PRIMITIVE_TYPES):
- # empty list or primitive types
- result[attr] = value
- elif isinstance(value[0], ModelSimple):
- result[attr] = [x.value for x in value]
- else:
- result[attr] = [model_to_dict(x, serialize=serialize) for x in value]
+ if not value:
+ # empty list or None
+ result[attr] = value
+ else:
+ res = []
+ for v in value:
+ if isinstance(v, PRIMITIVE_TYPES) or v is None:
+ res.append(v)
+ elif isinstance(v, ModelSimple):
+ res.append(v.value)
+ else:
+ res.append(model_to_dict(v, serialize=serialize))
+ result[attr] = res
elif isinstance(value, dict):
result[attr] = dict(map(
lambda item: (item[0],
@@ -1277,11 +1283,16 @@ def get_valid_classes_phrase(input_classes):
def convert_js_args_to_python_args(fn):
from functools import wraps
@wraps(fn)
- def wrapped_init(self, *args, **kwargs):
+ def wrapped_init(_self, *args, **kwargs):
+ """
+ An attribute named `self` received from the api will conflicts with the reserved `self`
+ parameter of a class method. During generation, `self` attributes are mapped
+ to `_self` in models. Here, we name `_self` instead of `self` to avoid conflicts.
+ """
spec_property_naming = kwargs.get('_spec_property_naming', False)
if spec_property_naming:
- kwargs = change_keys_js_to_python(kwargs, self.__class__)
- return fn(self, *args, **kwargs)
+ kwargs = change_keys_js_to_python(kwargs, _self.__class__)
+ return fn(_self, *args, **kwargs)
return wrapped_init
@@ -1291,8 +1302,13 @@ def get_allof_instances(self, model_args, constant_args):
self: the class we are handling
model_args (dict): var_name to var_value
used to make instances
- constant_args (dict): var_name to var_value
- used to make instances
+ constant_args (dict):
+ metadata arguments:
+ _check_type
+ _path_to_item
+ _spec_property_naming
+ _configuration
+ _visited_composed_classes
Returns
composed_instances (list)
@@ -1300,20 +1316,8 @@ def get_allof_instances(self, model_args, constant_args):
composed_instances = []
for allof_class in self._composed_schemas['allOf']:
- # no need to handle changing js keys to python because
- # for composed schemas, allof parameters are included in the
- # composed schema and were changed to python keys in __new__
- # extract a dict of only required keys from fixed_model_args
- kwargs = {}
- var_names = set(allof_class.openapi_types.keys())
- for var_name in var_names:
- if var_name in model_args:
- kwargs[var_name] = model_args[var_name]
-
- # and use it to make the instance
- kwargs.update(constant_args)
try:
- allof_instance = allof_class(**kwargs)
+ allof_instance = allof_class(**model_args, **constant_args)
composed_instances.append(allof_instance)
except Exception as ex:
raise ApiValueError(
@@ -1373,31 +1377,9 @@ def get_oneof_instance(cls, model_kwargs, constant_kwargs, model_arg=None):
single_value_input = allows_single_value_input(oneof_class)
- if not single_value_input:
- # transform js keys from input data to python keys in fixed_model_args
- fixed_model_args = change_keys_js_to_python(
- model_kwargs, oneof_class)
-
- # Extract a dict with the properties that are declared in the oneOf schema.
- # Undeclared properties (e.g. properties that are allowed because of the
- # additionalProperties attribute in the OAS document) are not added to
- # the dict.
- kwargs = {}
- var_names = set(oneof_class.openapi_types.keys())
- for var_name in var_names:
- if var_name in fixed_model_args:
- kwargs[var_name] = fixed_model_args[var_name]
-
- # do not try to make a model with no input args
- if len(kwargs) == 0:
- continue
-
- # and use it to make the instance
- kwargs.update(constant_kwargs)
-
try:
if not single_value_input:
- oneof_instance = oneof_class(**kwargs)
+ oneof_instance = oneof_class(**model_kwargs, **constant_kwargs)
else:
if issubclass(oneof_class, ModelSimple):
oneof_instance = oneof_class(model_arg, **constant_kwargs)
@@ -1454,24 +1436,8 @@ def get_anyof_instances(self, model_args, constant_args):
# none_type deserialization is handled in the __new__ method
continue
- # transform js keys to python keys in fixed_model_args
- fixed_model_args = change_keys_js_to_python(model_args, anyof_class)
-
- # extract a dict of only required keys from these_model_vars
- kwargs = {}
- var_names = set(anyof_class.openapi_types.keys())
- for var_name in var_names:
- if var_name in fixed_model_args:
- kwargs[var_name] = fixed_model_args[var_name]
-
- # do not try to make a model with no input args
- if len(kwargs) == 0:
- continue
-
- # and use it to make the instance
- kwargs.update(constant_args)
try:
- anyof_instance = anyof_class(**kwargs)
+ anyof_instance = anyof_class(**model_args, **constant_args)
anyof_instances.append(anyof_instance)
except Exception:
pass
@@ -1484,47 +1450,34 @@ def get_anyof_instances(self, model_args, constant_args):
return anyof_instances
-def get_additional_properties_model_instances(
- composed_instances, self):
- additional_properties_model_instances = []
- all_instances = [self]
- all_instances.extend(composed_instances)
- for instance in all_instances:
- if instance.additional_properties_type is not None:
- additional_properties_model_instances.append(instance)
- return additional_properties_model_instances
-
-
-def get_var_name_to_model_instances(self, composed_instances):
- var_name_to_model_instances = {}
- all_instances = [self]
- all_instances.extend(composed_instances)
- for instance in all_instances:
- for var_name in instance.openapi_types:
- if var_name not in var_name_to_model_instances:
- var_name_to_model_instances[var_name] = [instance]
- else:
- var_name_to_model_instances[var_name].append(instance)
- return var_name_to_model_instances
-
-
-def get_unused_args(self, composed_instances, model_args):
- unused_args = dict(model_args)
- # arguments apssed to self were already converted to python names
+def get_discarded_args(self, composed_instances, model_args):
+ """
+ Gathers the args that were discarded by configuration.discard_unknown_keys
+ """
+ model_arg_keys = model_args.keys()
+ discarded_args = set()
+ # arguments passed to self were already converted to python names
# before __init__ was called
- for var_name_py in self.attribute_map:
- if var_name_py in unused_args:
- del unused_args[var_name_py]
for instance in composed_instances:
if instance.__class__ in self._composed_schemas['allOf']:
- for var_name_py in instance.attribute_map:
- if var_name_py in unused_args:
- del unused_args[var_name_py]
+ try:
+ keys = instance.to_dict().keys()
+ discarded_keys = model_args - keys
+ discarded_args.update(discarded_keys)
+ except Exception:
+ # allOf integer schema will throw exception
+ pass
else:
- for var_name_js in instance.attribute_map.values():
- if var_name_js in unused_args:
- del unused_args[var_name_js]
- return unused_args
+ try:
+ all_keys = set(model_to_dict(instance, serialize=False).keys())
+ js_keys = model_to_dict(instance, serialize=True).keys()
+ all_keys.update(js_keys)
+ discarded_keys = model_arg_keys - all_keys
+ discarded_args.update(discarded_keys)
+ except Exception:
+ # allOf integer schema will throw exception
+ pass
+ return discarded_args
def validate_get_composed_info(constant_args, model_args, self):
@@ -1568,36 +1521,42 @@ def validate_get_composed_info(constant_args, model_args, self):
composed_instances.append(oneof_instance)
anyof_instances = get_anyof_instances(self, model_args, constant_args)
composed_instances.extend(anyof_instances)
+ """
+ set additional_properties_model_instances
+ additional properties must be evaluated at the schema level
+ so self's additional properties are most important
+ If self is a composed schema with:
+ - no properties defined in self
+ - additionalProperties: False
+ Then for object payloads every property is an additional property
+ and they are not allowed, so only empty dict is allowed
+
+ Properties must be set on all matching schemas
+ so when a property is assigned toa composed instance, it must be set on all
+ composed instances regardless of additionalProperties presence
+ keeping it to prevent breaking changes in v5.0.1
+ TODO remove cls._additional_properties_model_instances in 6.0.0
+ """
+ additional_properties_model_instances = []
+ if self.additional_properties_type is not None:
+ additional_properties_model_instances = [self]
+
+ """
+ no need to set properties on self in here, they will be set in __init__
+ By here all composed schema oneOf/anyOf/allOf instances have their properties set using
+ model_args
+ """
+ discarded_args = get_discarded_args(self, composed_instances, model_args)
# map variable names to composed_instances
- var_name_to_model_instances = get_var_name_to_model_instances(
- self, composed_instances)
-
- # set additional_properties_model_instances
- additional_properties_model_instances = (
- get_additional_properties_model_instances(composed_instances, self)
- )
-
- # set any remaining values
- unused_args = get_unused_args(self, composed_instances, model_args)
- if len(unused_args) > 0 and \
- len(additional_properties_model_instances) == 0 and \
- (self._configuration is None or
- not self._configuration.discard_unknown_keys):
- raise ApiValueError(
- "Invalid input arguments input when making an instance of "
- "class %s. Not all inputs were used. The unused input data "
- "is %s" % (self.__class__.__name__, unused_args)
- )
-
- # no need to add additional_properties to var_name_to_model_instances here
- # because additional_properties_model_instances will direct us to that
- # instance when we use getattr or setattr
- # and we update var_name_to_model_instances in setattr
+ var_name_to_model_instances = {}
+ for prop_name in model_args:
+ if prop_name not in discarded_args:
+ var_name_to_model_instances[prop_name] = [self] + composed_instances
return [
composed_instances,
var_name_to_model_instances,
additional_properties_model_instances,
- unused_args
+ discarded_args
]
diff --git a/modules/openapi-generator/src/main/resources/ruby-sinatra-server/Dockerfile b/modules/openapi-generator/src/main/resources/ruby-sinatra-server/Dockerfile
new file mode 100644
index 00000000000..41be83d48ec
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/ruby-sinatra-server/Dockerfile
@@ -0,0 +1,32 @@
+## Build libraries
+FROM ruby:3.0-alpine as rubydev
+
+## for thin or falcon
+#RUN apk --no-cache add make g++ libc-dev
+## for puma
+#RUN apk --no-cache add make gcc libc-dev
+
+ADD . /app
+WORKDIR /app
+
+RUN bundle config set path lib
+RUN bundle install
+
+## Build Runtime image
+FROM ruby:3.0-alpine
+
+RUN apk --no-cache add tzdata ## ca-certificates
+
+COPY --from=rubydev /app /app
+WORKDIR /app
+
+ENV SINATRA_HOST 0.0.0.0
+ENV SINATRA_PORT 8080
+EXPOSE $SINATRA_PORT
+
+RUN addgroup sinatra
+RUN adduser -S -G sinatra sinatra
+USER sinatra
+RUN bundle config set path lib
+
+CMD bundle exec rackup --host $SINATRA_HOST -p $SINATRA_PORT
diff --git a/modules/openapi-generator/src/main/resources/ruby-sinatra-server/Gemfile b/modules/openapi-generator/src/main/resources/ruby-sinatra-server/Gemfile
index be9c3168ea6..90d7b0e3bcd 100644
--- a/modules/openapi-generator/src/main/resources/ruby-sinatra-server/Gemfile
+++ b/modules/openapi-generator/src/main/resources/ruby-sinatra-server/Gemfile
@@ -1,4 +1,5 @@
source 'https://rubygems.org'
+gem "webrick"
gem "sinatra"
-gem "sinatra-cross_origin"
\ No newline at end of file
+gem "sinatra-cross_origin"
diff --git a/modules/openapi-generator/src/main/resources/ruby-sinatra-server/README.md b/modules/openapi-generator/src/main/resources/ruby-sinatra-server/README.md
index bf132cb042a..aecb705a194 100644
--- a/modules/openapi-generator/src/main/resources/ruby-sinatra-server/README.md
+++ b/modules/openapi-generator/src/main/resources/ruby-sinatra-server/README.md
@@ -1,4 +1,4 @@
-# Swagger for Sinatra
+# OpenAPI for Sinatra
## Overview
This is a project to provide Swagger support inside the [Sinatra](http://www.sinatrarb.com/) framework. You can find
@@ -6,24 +6,60 @@ out more about both the spec and the framework at http://swagger.io. For more i
Wordnik's APIs, please visit http://developer.wordnik.com.
## Prerequisites
-You need to install ruby 1.9.3 and the following gems:
+As of ruby 3.0.0, the webrick web server library was removed.
+You need to install a rack-supported web server, such as webrick and thin.
+
+The default Gemfile is as follows.
+Update the name of the web server as your prefer.
```
-sinatra
-sinatra-cross_origin
+source 'https://rubygems.org'
+
+gem "webrick"
+gem "sinatra"
+gem "sinatra-cross_origin"
```
## Getting started
-This sample was generated with the [OpenAPI Generator](https://github.com/openapitools/openapi-generator) project.
+To generate a ruby-sinatra server for petstore.yaml, please run the following:
```
-rackup -p 4567 config.ru
+openapi-generator-cli generate \
+ -i https://raw.githubusercontent.com/openapitools/openapi-generator/master/modules/openapi-generator/src/test/resources/3_0/petstore.yaml \
+ -g ruby-sinatra -o code
```
-In your [swagger ui](https://github.com/swagger-api/swagger-ui), put in the following URL:
+To run the generated server, please run the following:
```
-http://localhost:4567/resources.json
+cd code/
+bundle config set path lib
+bundle install
+bundle exec rackup -p 8080
+```
+
+You can access the application by the following URL:
+
+```
+http://localhost:8080/v2/store/inventory
+```
+
+## Docker
+If you want to use a web server other than webrick, you need to edit the generated Dockerfile to prepare the compiler and the make command. Please check the comment of the Dockerfile.
+
+To run the code on docker, you can use the Dockerfile as follows:
+
+### Build the docker image
+The "container_name" can be changed for your preferences.
+
+```
+docker build . --tag "container_name"
+```
+
+### Run the docker image
+
+```
+docker run -it --rm -p 8080:8080 "container_name"
```
Voila!
diff --git a/modules/openapi-generator/src/main/resources/scala-akka-client/requests.mustache b/modules/openapi-generator/src/main/resources/scala-akka-client/requests.mustache
index 6dd3ab7d977..727d88f1818 100644
--- a/modules/openapi-generator/src/main/resources/scala-akka-client/requests.mustache
+++ b/modules/openapi-generator/src/main/resources/scala-akka-client/requests.mustache
@@ -3,6 +3,7 @@ package {{invokerPackage}}
import java.io.File
import java.net.URLEncoder
+import java.util.UUID
import java.time.OffsetDateTime
import scala.util.Try
@@ -181,6 +182,7 @@ object ParametersMap {
case Some(opt) => formattedParams(name, opt)
case s: Seq[Any] => formattedParams(name, ArrayValues(s))
case v: String => Seq((name, urlEncode(v)))
+ case v: UUID => formattedParams(name, v.toString)
case NumericValue(v) => Seq((name, urlEncode(v)))
case f: File => Seq((name, f))
case m: ApiModel => Seq((name, m))
diff --git a/modules/openapi-generator/src/main/resources/scala-akka-client/serializers.mustache b/modules/openapi-generator/src/main/resources/scala-akka-client/serializers.mustache
index 6fcbaa2c35e..e66999529d9 100644
--- a/modules/openapi-generator/src/main/resources/scala-akka-client/serializers.mustache
+++ b/modules/openapi-generator/src/main/resources/scala-akka-client/serializers.mustache
@@ -9,6 +9,7 @@ import org.joda.time.format.ISODateTimeFormat
import org.joda.time.{LocalDate, DateTime}
{{/joda}}
import org.json4s.{Serializer, CustomSerializer, JNull}
+import org.json4s.ext.JavaTypesSerializers
import org.json4s.JsonAST.JString
import scala.util.Try
@@ -47,6 +48,6 @@ object Serializers {
}))
{{/joda}}
- def all: Seq[Serializer[_]] = Seq[Serializer[_]]() :+ DateTimeSerializer :+ LocalDateSerializer
+ def all: Seq[Serializer[_]] = JavaTypesSerializers.all :+ DateTimeSerializer :+ LocalDateSerializer
-}
\ No newline at end of file
+}
diff --git a/modules/openapi-generator/src/main/resources/scala-akka-http-server/multipartDirectives.mustache b/modules/openapi-generator/src/main/resources/scala-akka-http-server/multipartDirectives.mustache
index 98a2186fd2e..6e802204c57 100644
--- a/modules/openapi-generator/src/main/resources/scala-akka-http-server/multipartDirectives.mustache
+++ b/modules/openapi-generator/src/main/resources/scala-akka-http-server/multipartDirectives.mustache
@@ -1,6 +1,7 @@
package {{invokerPackage}}
import java.io.File
+import java.nio.file.Files
import akka.annotation.ApiMayChange
import akka.http.scaladsl.model.Multipart.FormData
@@ -69,7 +70,7 @@ trait MultipartDirectives {
object MultipartDirectives extends MultipartDirectives with FileUploadDirectives {
val tempFileFromFileInfo: FileInfo => File = {
- file: FileInfo => File.createTempFile(file.fileName, ".tmp")
+ file: FileInfo => Files.createTempFile(file.fileName, ".tmp").toFile()
}
}
diff --git a/modules/openapi-generator/src/main/resources/swift5/Cartfile.mustache b/modules/openapi-generator/src/main/resources/swift5/Cartfile.mustache
index 3f6269c23ab..64dac06473e 100644
--- a/modules/openapi-generator/src/main/resources/swift5/Cartfile.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/Cartfile.mustache
@@ -1,3 +1,4 @@
{{#useAlamofire}}github "Alamofire/Alamofire" ~> 4.9.1{{/useAlamofire}}{{#usePromiseKit}}
github "mxcl/PromiseKit" ~> 6.13.1{{/usePromiseKit}}{{#useRxSwift}}
github "ReactiveX/RxSwift" ~> 5.1.1{{/useRxSwift}}
+github "Flight-School/AnyCodable" ~> 0.4.0
diff --git a/modules/openapi-generator/src/main/resources/swift5/Extensions.mustache b/modules/openapi-generator/src/main/resources/swift5/Extensions.mustache
index 1a23697a04b..7e6dcc1994f 100644
--- a/modules/openapi-generator/src/main/resources/swift5/Extensions.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/Extensions.mustache
@@ -4,7 +4,8 @@
// https://openapi-generator.tech
//
-import Foundation{{#usePromiseKit}}
+import Foundation
+import AnyCodable{{#usePromiseKit}}
import PromiseKit{{/usePromiseKit}}
extension Bool: JSONEncodable {
@@ -53,6 +54,12 @@ extension Array: JSONEncodable {
}
}
+extension Set: JSONEncodable {
+ func encodeToJSON() -> Any {
+ return Array(self).encodeToJSON()
+ }
+}
+
extension Dictionary: JSONEncodable {
func encodeToJSON() -> Any {
var dictionary = [AnyHashable: Any]()
@@ -193,3 +200,44 @@ extension RequestBuilder {
return deferred.promise
}
}{{/usePromiseKit}}
+
+extension AnyCodable: Hashable {
+ public func hash(into hasher: inout Hasher) {
+ switch value {
+ case let value as Bool:
+ hasher.combine(value)
+ case let value as Int:
+ hasher.combine(value)
+ case let value as Int8:
+ hasher.combine(value)
+ case let value as Int16:
+ hasher.combine(value)
+ case let value as Int32:
+ hasher.combine(value)
+ case let value as Int64:
+ hasher.combine(value)
+ case let value as UInt:
+ hasher.combine(value)
+ case let value as UInt8:
+ hasher.combine(value)
+ case let value as UInt16:
+ hasher.combine(value)
+ case let value as UInt32:
+ hasher.combine(value)
+ case let value as UInt64:
+ hasher.combine(value)
+ case let value as Float:
+ hasher.combine(value)
+ case let value as Double:
+ hasher.combine(value)
+ case let value as String:
+ hasher.combine(value)
+ case let value as [String: AnyCodable]:
+ hasher.combine(value)
+ case let value as [AnyCodable]:
+ hasher.combine(value)
+ default:
+ hasher.combine(0)
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/swift5/Package.swift.mustache b/modules/openapi-generator/src/main/resources/swift5/Package.swift.mustache
index d173f21077b..353c6e9f341 100644
--- a/modules/openapi-generator/src/main/resources/swift5/Package.swift.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/Package.swift.mustache
@@ -1,4 +1,4 @@
-// swift-tools-version:5.0
+// swift-tools-version:5.1
import PackageDescription
@@ -19,6 +19,7 @@ let package = Package(
],
dependencies: [
// Dependencies declare other packages that this package depends on.
+ .package(url: "https://github.com/Flight-School/AnyCodable", .exact("0.4.0")),
{{#useAlamofire}}
.package(url: "https://github.com/Alamofire/Alamofire.git", from: "4.9.1"),
{{/useAlamofire}}
@@ -34,8 +35,8 @@ let package = Package(
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "{{projectName}}",
- dependencies: [{{#useAlamofire}}"Alamofire", {{/useAlamofire}}{{#usePromiseKit}}"PromiseKit", {{/usePromiseKit}}{{#useRxSwift}}"RxSwift"{{/useRxSwift}}],
- path: "{{projectName}}/Classes"
+ dependencies: ["AnyCodable", {{#useAlamofire}}"Alamofire", {{/useAlamofire}}{{#usePromiseKit}}"PromiseKit", {{/usePromiseKit}}{{#useRxSwift}}"RxSwift"{{/useRxSwift}}],
+ path: "{{#swiftPackagePath}}{{swiftPackagePath}}{{/swiftPackagePath}}{{^swiftPackagePath}}{{#useSPMFileStructure}}Sources/{{projectName}}{{/useSPMFileStructure}}{{^useSPMFileStructure}}{{projectName}}/Classes{{/useSPMFileStructure}}{{/swiftPackagePath}}"
),
]
)
diff --git a/modules/openapi-generator/src/main/resources/swift5/Podspec.mustache b/modules/openapi-generator/src/main/resources/swift5/Podspec.mustache
index c0539662ce7..09f07162c03 100644
--- a/modules/openapi-generator/src/main/resources/swift5/Podspec.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/Podspec.mustache
@@ -25,7 +25,7 @@ Pod::Spec.new do |s|
{{#podDocumentationURL}}
s.documentation_url = '{{podDocumentationURL}}'
{{/podDocumentationURL}}
- s.source_files = '{{projectName}}/Classes/**/*.swift'
+ s.source_files = '{{#swiftPackagePath}}{{swiftPackagePath}}{{/swiftPackagePath}}{{^swiftPackagePath}}{{#useSPMFileStructure}}Sources/{{projectName}}{{/useSPMFileStructure}}{{^useSPMFileStructure}}{{projectName}}/Classes{{/useSPMFileStructure}}{{/swiftPackagePath}}/**/*.swift'
{{#usePromiseKit}}
s.dependency 'PromiseKit/CorePromise', '~> 6.13.1'
{{/usePromiseKit}}
@@ -35,4 +35,5 @@ Pod::Spec.new do |s|
{{#useAlamofire}}
s.dependency 'Alamofire', '~> 4.9.1'
{{/useAlamofire}}
+ s.dependency 'AnyCodable-FlightSchool', '~> 0.4.0'
end
diff --git a/modules/openapi-generator/src/main/resources/swift5/XcodeGen.mustache b/modules/openapi-generator/src/main/resources/swift5/XcodeGen.mustache
index a81137ae138..54fbb33d468 100644
--- a/modules/openapi-generator/src/main/resources/swift5/XcodeGen.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/XcodeGen.mustache
@@ -4,7 +4,7 @@ targets:
type: framework
platform: iOS
deploymentTarget: "9.0"
- sources: [{{projectName}}]
+ sources: [{{#swiftPackagePath}}{{swiftPackagePath}}{{/swiftPackagePath}}{{^swiftPackagePath}}{{#useSPMFileStructure}}Sources{{/useSPMFileStructure}}{{^useSPMFileStructure}}{{projectName}}{{/useSPMFileStructure}}{{/swiftPackagePath}}]
info:
path: ./Info.plist
version: {{#podVersion}}{{podVersion}}{{/podVersion}}{{^podVersion}}{{#apiInfo}}{{version}}{{/apiInfo}}{{^apiInfo}}}0.0.1{{/apiInfo}}{{/podVersion}}
@@ -15,3 +15,4 @@ targets:
- carthage: Alamofire{{/useAlamofire}}{{#useRxSwift}}
- carthage: RxSwift{{/useRxSwift}}{{#usePromiseKit}}
- carthage: PromiseKit{{/usePromiseKit}}
+ - carthage: AnyCodable
diff --git a/modules/openapi-generator/src/main/resources/swift5/api.mustache b/modules/openapi-generator/src/main/resources/swift5/api.mustache
index f1e181e2524..ac3b4b3d954 100644
--- a/modules/openapi-generator/src/main/resources/swift5/api.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/api.mustache
@@ -248,13 +248,13 @@ extension {{projectName}}API {
let parameters: [String: Any]? = nil
{{/hasFormParams}}
{{/bodyParam}}{{#hasQueryParams}}
- var url = URLComponents(string: URLString)
- url?.queryItems = APIHelper.mapValuesToQueryItems([{{^queryParams}}:{{/queryParams}}
+ var urlComponents = URLComponents(string: URLString)
+ urlComponents?.queryItems = APIHelper.mapValuesToQueryItems([{{^queryParams}}:{{/queryParams}}
{{#queryParams}}
{{> _param}},
{{/queryParams}}
]){{/hasQueryParams}}{{^hasQueryParams}}
- let url = URLComponents(string: URLString){{/hasQueryParams}}
+ let urlComponents = URLComponents(string: URLString){{/hasQueryParams}}
let nillableHeaders: [String: Any?] = [{{^headerParams}}{{^hasFormParams}}
:{{/hasFormParams}}{{/headerParams}}{{#hasFormParams}}
@@ -266,7 +266,7 @@ extension {{projectName}}API {
let requestBuilder: RequestBuilder<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>.Type = {{projectName}}API.requestBuilderFactory.{{#returnType}}getBuilder(){{/returnType}}{{^returnType}}getNonDecodableBuilder(){{/returnType}}
- return requestBuilder.init(method: "{{httpMethod}}", URLString: (url?.string ?? URLString), parameters: parameters, headers: headerParameters)
+ return requestBuilder.init(method: "{{httpMethod}}", URLString: (urlComponents?.string ?? URLString), parameters: parameters, headers: headerParameters)
}
{{/operation}}
diff --git a/modules/openapi-generator/src/main/resources/swift5/model.mustache b/modules/openapi-generator/src/main/resources/swift5/model.mustache
index a5870644a60..7ea71a27f23 100644
--- a/modules/openapi-generator/src/main/resources/swift5/model.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/model.mustache
@@ -6,6 +6,7 @@
//
import Foundation
+import AnyCodable
{{#description}}
/** {{description}} */{{/description}}{{#isDeprecated}}
diff --git a/modules/openapi-generator/src/main/resources/swift5/modelObject.mustache b/modules/openapi-generator/src/main/resources/swift5/modelObject.mustache
index 661bb479b48..c119f723a2a 100644
--- a/modules/openapi-generator/src/main/resources/swift5/modelObject.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/modelObject.mustache
@@ -1,4 +1,4 @@
-{{^objcCompatible}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} struct {{classname}}: Codable{{#vendorExtensions.x-swift-hashable}}, Hashable{{/vendorExtensions.x-swift-hashable}} {
+{{^objcCompatible}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} {{#useClasses}}final class{{/useClasses}}{{^useClasses}}struct{{/useClasses}} {{classname}}: Codable, Hashable {
{{/objcCompatible}}{{#objcCompatible}}@objc {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} class {{classname}}: NSObject, Codable {
{{/objcCompatible}}
@@ -11,17 +11,17 @@
{{#isEnum}}
{{#description}}/** {{description}} */
{{/description}}{{#deprecated}}@available(*, deprecated, message: "This property is deprecated.")
- {{/deprecated}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} {{#readonlyProperties}}private(set) {{/readonlyProperties}}var {{name}}: {{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}
+ {{/deprecated}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} {{#readonlyProperties}}private(set) {{/readonlyProperties}}var {{{name}}}: {{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}
{{/isEnum}}
{{^isEnum}}
{{#description}}/** {{description}} */
{{/description}}{{#deprecated}}@available(*, deprecated, message: "This property is deprecated.")
- {{/deprecated}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} {{#readonlyProperties}}private(set) {{/readonlyProperties}}var {{name}}: {{{datatype}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}
+ {{/deprecated}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} {{#readonlyProperties}}private(set) {{/readonlyProperties}}var {{{name}}}: {{{datatype}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}
{{#objcCompatible}}
{{#vendorExtensions.x-swift-optional-scalar}}
- {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var {{name}}Num: NSNumber? {
+ {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var {{{name}}}Num: NSNumber? {
get {
- return {{name}} as NSNumber?
+ return {{{name}}} as NSNumber?
}
}
{{/vendorExtensions.x-swift-optional-scalar}}
@@ -30,12 +30,17 @@
{{/allVars}}
{{#hasVars}}
- {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} init({{#allVars}}{{name}}: {{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}{{^required}} = nil{{/required}}{{/defaultValue}}{{^-last}}, {{/-last}}{{/allVars}}) {
+ {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} init({{#allVars}}{{{name}}}: {{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}{{^required}} = nil{{/required}}{{/defaultValue}}{{^-last}}, {{/-last}}{{/allVars}}) {
{{#allVars}}
- self.{{name}} = {{name}}
+ self.{{{name}}} = {{{name}}}
{{/allVars}}
}
{{/hasVars}}
+ {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum CodingKeys: {{#hasVars}}String, {{/hasVars}}CodingKey, CaseIterable {
+ {{#allVars}}
+ case {{{name}}}{{#vendorExtensions.x-codegen-escaped-property-name}} = "{{{baseName}}}"{{/vendorExtensions.x-codegen-escaped-property-name}}
+ {{/allVars}}
+ }
{{#additionalPropertiesType}}
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} {{#readonlyProperties}}private(set) {{/readonlyProperties}}var additionalProperties: [String: {{{additionalPropertiesType}}}] = [:]
@@ -51,26 +56,29 @@
additionalProperties[key] = newValue
}
}
+{{/additionalPropertiesType}}
// Encodable protocol methods
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func encode(to encoder: Encoder) throws {
-
- var container = encoder.container(keyedBy: String.self)
-
+ var container = encoder.container(keyedBy: CodingKeys.self)
{{#allVars}}
- try container.encode{{#required}}{{#isNullable}}IfPresent{{/isNullable}}{{/required}}{{^required}}IfPresent{{/required}}({{{name}}}, forKey: "{{{baseName}}}")
+ try container.encode{{^required}}IfPresent{{/required}}({{{name}}}, forKey: .{{{name}}})
{{/allVars}}
- try container.encodeMap(additionalProperties)
+ {{#additionalPropertiesType}}
+ var additionalPropertiesContainer = encoder.container(keyedBy: String.self)
+ try additionalPropertiesContainer.encodeMap(additionalProperties)
+ {{/additionalPropertiesType}}
}
+{{#additionalPropertiesType}}
// Decodable protocol methods
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}}{{#objcCompatible}} required{{/objcCompatible}} init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: String.self)
{{#allVars}}
- {{name}} = try container.decode{{#required}}{{#isNullable}}IfPresent{{/isNullable}}{{/required}}{{^required}}IfPresent{{/required}}({{{datatypeWithEnum}}}.self, forKey: "{{{baseName}}}")
+ {{{name}}} = try container.decode{{#required}}{{#isNullable}}IfPresent{{/isNullable}}{{/required}}{{^required}}IfPresent{{/required}}({{{datatypeWithEnum}}}.self, forKey: "{{{baseName}}}")
{{/allVars}}
var nonAdditionalPropertyKeys = Set()
{{#allVars}}
@@ -79,11 +87,20 @@
additionalProperties = try container.decodeMap({{{additionalPropertiesType}}}.self, excludedKeys: nonAdditionalPropertyKeys)
}
{{/additionalPropertiesType}}
-{{^additionalPropertiesType}}{{#vendorExtensions.x-codegen-has-escaped-property-names}}
- {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum CodingKeys: String, CodingKey, CaseIterable {
+
+{{^objcCompatible}}{{#useClasses}}
+ {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static func == (lhs: {{classname}}, rhs: {{classname}}) -> Bool {
{{#allVars}}
- case {{name}}{{#vendorExtensions.x-codegen-escaped-property-name}} = "{{{baseName}}}"{{/vendorExtensions.x-codegen-escaped-property-name}}
+ lhs.{{{name}}} == rhs.{{{name}}}{{^-last}} &&{{/-last}}
{{/allVars}}
+ {{#additionalPropertiesType}}{{#hasVars}}&& {{/hasVars}}lhs.additionalProperties == rhs.additionalProperties{{/additionalPropertiesType}}
}
-{{/vendorExtensions.x-codegen-has-escaped-property-names}}{{/additionalPropertiesType}}
+
+ {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func hash(into hasher: inout Hasher) {
+ {{#allVars}}
+ hasher.combine({{{name}}}{{^required}}?{{/required}}.hashValue)
+ {{/allVars}}
+ {{#additionalPropertiesType}}hasher.combine(additionalProperties.hashValue){{/additionalPropertiesType}}
+ }
+{{/useClasses}}{{/objcCompatible}}
}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/swift5/model_doc.mustache b/modules/openapi-generator/src/main/resources/swift5/model_doc.mustache
index d3e4ecf5c76..6b68575707a 100644
--- a/modules/openapi-generator/src/main/resources/swift5/model_doc.mustache
+++ b/modules/openapi-generator/src/main/resources/swift5/model_doc.mustache
@@ -3,7 +3,7 @@
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
-{{#vars}}**{{name}}** | {{#isPrimitiveType}}**{{{dataType}}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{^isContainer}}[**{{dataType}}**]({{complexType}}.md){{/isContainer}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}}
+{{#vars}}**{{{name}}}** | {{#isPrimitiveType}}**{{{dataType}}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{^isContainer}}[**{{dataType}}**]({{complexType}}.md){{/isContainer}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}}
{{/vars}}
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
diff --git a/modules/openapi-generator/src/main/resources/typescript-angular/api.service.mustache b/modules/openapi-generator/src/main/resources/typescript-angular/api.service.mustache
index 718a8b88549..8f66fcf6f9e 100644
--- a/modules/openapi-generator/src/main/resources/typescript-angular/api.service.mustache
+++ b/modules/openapi-generator/src/main/resources/typescript-angular/api.service.mustache
@@ -334,9 +334,9 @@ export class {{classname}} {
{{/hasFormParams}}
{{^isResponseFile}}
- let responseType: 'text' | 'json' = 'json';
+ let responseType_: 'text' | 'json' = 'json';
if(httpHeaderAcceptSelected && httpHeaderAcceptSelected.startsWith('text')) {
- responseType = 'text';
+ responseType_ = 'text';
}
{{/isResponseFile}}
@@ -350,7 +350,7 @@ export class {{classname}} {
responseType: "blob",
{{/isResponseFile}}
{{^isResponseFile}}
- responseType: responseType,
+ responseType: responseType_,
{{/isResponseFile}}
withCredentials: this.configuration.withCredentials,
headers: headers,
diff --git a/modules/openapi-generator/src/main/resources/typescript-angular/configuration.mustache b/modules/openapi-generator/src/main/resources/typescript-angular/configuration.mustache
index e3a5e824385..40aaec67f47 100644
--- a/modules/openapi-generator/src/main/resources/typescript-angular/configuration.mustache
+++ b/modules/openapi-generator/src/main/resources/typescript-angular/configuration.mustache
@@ -64,15 +64,19 @@ export class {{configurationClassName}} {
{{#isApiKey}}
this.credentials['{{name}}'] = () => {
{{! Fallback behaviour may be removed for 5.0 release. See #5062 }}
- return this.apiKeys['{{name}}'] || this.apiKeys['{{keyParamName}}'];
+ if (this.apiKeys === null || this.apiKeys === undefined) {
+ return undefined;
+ } else {
+ return this.apiKeys['{{name}}'] || this.apiKeys['{{keyParamName}}'];
+ }
};
{{/isApiKey}}
{{#isBasic}}
{{#isBasicBasic}}
this.credentials['{{name}}'] = () => {
- if (this.username || this.password) {
- return btoa(this.username + ':' + this.password);
- }
+ return (this.username || this.password)
+ ? btoa(this.username + ':' + this.password)
+ : undefined;
};
{{/isBasicBasic}}
{{#isBasicBearer}}
diff --git a/modules/openapi-generator/src/main/resources/typescript-axios/apiInner.mustache b/modules/openapi-generator/src/main/resources/typescript-axios/apiInner.mustache
index 71981cf8fca..0550c77b4d8 100644
--- a/modules/openapi-generator/src/main/resources/typescript-axios/apiInner.mustache
+++ b/modules/openapi-generator/src/main/resources/typescript-axios/apiInner.mustache
@@ -86,10 +86,20 @@ export const {{classname}}AxiosParamCreator = function (configuration?: Configur
{{#isArray}}
if ({{paramName}}) {
{{#isCollectionFormatMulti}}
+ {{#uniqueItems}}
+ localVarQueryParameter['{{baseName}}'] = Array.from({{paramName}});
+ {{/uniqueItems}}
+ {{^uniqueItems}}
localVarQueryParameter['{{baseName}}'] = {{paramName}};
+ {{/uniqueItems}}
{{/isCollectionFormatMulti}}
{{^isCollectionFormatMulti}}
+ {{#uniqueItems}}
+ localVarQueryParameter['{{baseName}}'] = Array.from({{paramName}}).join(COLLECTION_FORMATS.{{collectionFormat}});
+ {{/uniqueItems}}
+ {{^uniqueItems}}
localVarQueryParameter['{{baseName}}'] = {{paramName}}.join(COLLECTION_FORMATS.{{collectionFormat}});
+ {{/uniqueItems}}
{{/isCollectionFormatMulti}}
}
{{/isArray}}
@@ -117,7 +127,12 @@ export const {{classname}}AxiosParamCreator = function (configuration?: Configur
{{#headerParams}}
{{#isArray}}
if ({{paramName}}) {
+ {{#uniqueItems}}
+ let mapped = Array.from({{paramName}}).map(value => ("{{{dataType}}}" !== "Set") ? JSON.stringify(value) : (value || ""));
+ {{/uniqueItems}}
+ {{^uniqueItems}}
let mapped = {{paramName}}.map(value => ("{{{dataType}}}" !== "Array") ? JSON.stringify(value) : (value || ""));
+ {{/uniqueItems}}
localVarHeaderParameter['{{baseName}}'] = mapped.join(COLLECTION_FORMATS["{{collectionFormat}}"]);
}
{{/isArray}}
@@ -143,7 +158,7 @@ export const {{classname}}AxiosParamCreator = function (configuration?: Configur
})
{{/isCollectionFormatMulti}}
{{^isCollectionFormatMulti}}
- localVarFormParams.{{#multipartFormData}}append{{/multipartFormData}}{{^multipartFormData}}set{{/multipartFormData}}({{paramName}}.join(COLLECTION_FORMATS.{{collectionFormat}}));
+ localVarFormParams.{{#multipartFormData}}append{{/multipartFormData}}{{^multipartFormData}}set{{/multipartFormData}}('{{baseName}}', {{paramName}}.join(COLLECTION_FORMATS.{{collectionFormat}}));
{{/isCollectionFormatMulti}}
}{{/isArray}}
{{^isArray}}
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java
index a21c506d5a2..e125c98a463 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java
@@ -1188,12 +1188,15 @@ public class DefaultCodegenTest {
Schema sc = openAPI.getComponents().getSchemas().get(modelName);
+ /*
+ // comment out below as we're now showing warnings instead of throwing exceptions
try {
codegen.fromModel(modelName, sc);
Assert.assertTrue(false, "A RuntimeException should have been thrown when processing "+modelName+ " but it was not");
} catch (RuntimeException re) {
Assert.assertEquals(re.getMessage(), errorMessageExpected);
}
+ */
}
}
@@ -1220,12 +1223,15 @@ public class DefaultCodegenTest {
Schema sc = openAPI.getComponents().getSchemas().get(modelName);
+ /*
+ // comment out below as we're now showing warnings instead of throwing exceptions
try {
codegen.fromModel(modelName, sc);
Assert.assertTrue(false, "A RuntimeException should have been thrown when processing "+modelName+ " but it was not");
} catch (RuntimeException re) {
Assert.assertEquals(re.getMessage(), errorMessageExpected);
}
+ */
}
}
@@ -1256,7 +1262,8 @@ public class DefaultCodegenTest {
// inline anyOf with inline anyOf model doesn't work because we have null $refs and we throw an exception
final String fmodelName = "FruitInlineInlineDisc";
final Schema fsc = openAPI.getComponents().getSchemas().get(fmodelName);
- Assert.assertThrows(() -> codegen.fromModel(fmodelName, fsc));
+ // comment out below as we're now showing warnings instead of throwing exceptions
+ //Assert.assertThrows(() -> codegen.fromModel(fmodelName, fsc));
// ref anyOf models with discriminator in properties in those models
modelName = "FruitReqDisc";
@@ -1341,7 +1348,8 @@ public class DefaultCodegenTest {
// inline oneOf with inline oneOf model doesn't work because we have null $refs and we throw an exception
final String fmodelName = "FruitInlineInlineDisc";
final Schema fsc = openAPI.getComponents().getSchemas().get(fmodelName);
- Assert.assertThrows(() -> codegen.fromModel(fmodelName, fsc));
+ // comment out below as we're now showing warnings instead of throwing exceptions
+ //Assert.assertThrows(() -> codegen.fromModel(fmodelName, fsc));
// ref oneOf models with discriminator in properties in those models
modelName = "FruitReqDisc";
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultGeneratorTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultGeneratorTest.java
index 1dee6ced301..7e6a986bb32 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultGeneratorTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultGeneratorTest.java
@@ -459,7 +459,7 @@ public class DefaultGeneratorTest {
List files = generator.opts(clientOptInput).generate();
- Assert.assertEquals(files.size(), 24);
+ Assert.assertEquals(files.size(), 26);
// Generator should report a library templated file as a generated file
TestUtils.ensureContainsFile(files, output, "src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt");
@@ -501,7 +501,7 @@ public class DefaultGeneratorTest {
List files = generator.opts(clientOptInput).generate();
- Assert.assertEquals(files.size(), 24);
+ Assert.assertEquals(files.size(), 26);
// Generator should report README.md as a generated file
TestUtils.ensureContainsFile(files, output, "README.md");
@@ -566,7 +566,7 @@ public class DefaultGeneratorTest {
List files = generator.opts(clientOptInput).generate();
- Assert.assertEquals(files.size(), 24);
+ Assert.assertEquals(files.size(), 26);
// Generator should report a library templated file as a generated file
TestUtils.ensureContainsFile(files, output, "src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt");
@@ -620,7 +620,7 @@ public class DefaultGeneratorTest {
List files = generator.opts(clientOptInput).generate();
- Assert.assertEquals(files.size(), 24);
+ Assert.assertEquals(files.size(), 26);
// Generator should report README.md as a generated file
TestUtils.ensureContainsFile(files, output, "README.md");
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/DartModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/DartModelTest.java
index 36daa8b1335..5d76dbcac8e 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/DartModelTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/DartModelTest.java
@@ -337,8 +337,8 @@ public class DartModelTest {
{"sample name", "SampleName"},
{"List", "ModelList"},
{"list", "ModelList"},
- {"File", "ModelFile"},
- {"Client", "ModelClient"},
+ {"File", "TestModelFile"},
+ {"Client", "TestModelClient"},
{"String", "ModelString"},
};
}
@@ -349,6 +349,8 @@ public class DartModelTest {
final Schema model = new Schema();
final DefaultCodegen codegen = new DartClientCodegen();
codegen.setOpenAPI(openAPI);
+ codegen.typeMapping().put("File", "TestModelFile");
+ codegen.typeMapping().put("Client", "TestModelClient");
final CodegenModel cm = codegen.fromModel(name, model);
Assert.assertEquals(cm.name, name);
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioModelTest.java
index 95449c3edb9..d645046b2df 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioModelTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioModelTest.java
@@ -380,10 +380,8 @@ public class DartDioModelTest {
@DataProvider(name = "modelNames")
public static Object[][] modelNames() {
return new Object[][] {
- {"EnumClass", "ModelEnumClass"},
- {"JsonObject", "ModelJsonObject"},
- // OffsetDate is valid without timemachine date library
- {"OffsetDate", "OffsetDate"},
+ {"EnumClass", "TestModelEnumClass"},
+ {"JsonObject", "TestModelJsonObject"}
};
}
@@ -393,6 +391,8 @@ public class DartDioModelTest {
final Schema model = new Schema();
final DartDioClientCodegen codegen = new DartDioClientCodegen();
codegen.setOpenAPI(openAPI);
+ codegen.typeMapping().put("EnumClass", "TestModelEnumClass");
+ codegen.typeMapping().put("JsonObject", "TestModelJsonObject");
final CodegenModel cm = codegen.fromModel(name, model);
Assert.assertEquals(cm.name, name);
@@ -402,10 +402,9 @@ public class DartDioModelTest {
@DataProvider(name = "modelNamesTimemachine")
public static Object[][] modelNamesTimemachine() {
return new Object[][] {
- {"EnumClass", "ModelEnumClass"},
- {"JsonObject", "ModelJsonObject"},
- // OffsetDate is not valid with timemachine date library
- {"OffsetDate", "ModelOffsetDate"},
+ {"EnumClass", "TestModelEnumClass"},
+ {"JsonObject", "TestModelJsonObject"},
+ {"OffsetDate", "TestModelOffsetDate"},
};
}
@@ -416,6 +415,9 @@ public class DartDioModelTest {
final DartDioClientCodegen codegen = new DartDioClientCodegen();
codegen.setDateLibrary("timemachine");
codegen.processOpts();
+ codegen.typeMapping().put("EnumClass", "TestModelEnumClass");
+ codegen.typeMapping().put("JsonObject", "TestModelJsonObject");
+ codegen.typeMapping().put("OffsetDate", "TestModelOffsetDate");
codegen.setOpenAPI(openAPI);
final CodegenModel cm = codegen.fromModel(name, model);
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioNextModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioNextModelTest.java
index 1190240faa0..4eefae4e418 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioNextModelTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioNextModelTest.java
@@ -390,10 +390,8 @@ public class DartDioNextModelTest {
@DataProvider(name = "modelNames")
public static Object[][] modelNames() {
return new Object[][] {
- {"EnumClass", "ModelEnumClass"},
- {"JsonObject", "ModelJsonObject"},
- // OffsetDate is valid without timemachine date library
- {"OffsetDate", "OffsetDate"},
+ {"EnumClass", "TestModelEnumClass"},
+ {"JsonObject", "TestModelJsonObject"},
};
}
@@ -405,7 +403,8 @@ public class DartDioNextModelTest {
final DefaultCodegen codegen = new DartDioNextClientCodegen();
codegen.additionalProperties().put(CodegenConstants.SERIALIZATION_LIBRARY, DartDioNextClientCodegen.SERIALIZATION_LIBRARY_BUILT_VALUE);
codegen.processOpts();
-
+ codegen.typeMapping().put("EnumClass", "TestModelEnumClass");
+ codegen.typeMapping().put("JsonObject", "TestModelJsonObject");
codegen.setOpenAPI(openAPI);
final CodegenModel cm = codegen.fromModel(name, model);
@@ -417,10 +416,9 @@ public class DartDioNextModelTest {
@DataProvider(name = "modelNamesTimemachine")
public static Object[][] modelNamesTimemachine() {
return new Object[][] {
- {"EnumClass", "ModelEnumClass"},
- {"JsonObject", "ModelJsonObject"},
- // OffsetDate is not valid with timemachine date library
- {"OffsetDate", "ModelOffsetDate"},
+ {"EnumClass", "TestModelEnumClass"},
+ {"JsonObject", "TestModelJsonObject"},
+ {"OffsetDate", "TestModelOffsetDate"},
};
}
@@ -431,7 +429,11 @@ public class DartDioNextModelTest {
final DartDioNextClientCodegen codegen = new DartDioNextClientCodegen();
codegen.additionalProperties().put(DartDioNextClientCodegen.DATE_LIBRARY, DartDioNextClientCodegen.DATE_LIBRARY_TIME_MACHINE);
codegen.processOpts();
+ codegen.typeMapping().put("EnumClass", "TestModelEnumClass");
+ codegen.typeMapping().put("JsonObject", "TestModelJsonObject");
+ codegen.typeMapping().put("OffsetDate", "TestModelOffsetDate");
codegen.setOpenAPI(openAPI);
+
final CodegenModel cm = codegen.fromModel(name, model);
Assert.assertEquals(cm.name, name);
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java
index 3ead6f31f9e..3a7636d631c 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java
@@ -1028,18 +1028,18 @@ public class JavaClientCodegenTest {
Path defaultApi = Paths.get(output + "/src/main/java/xyz/abcdef/api/MultipartApi.java");
TestUtils.assertFileContains(defaultApi,
//multiple files
- "multipartArray(java.util.Collection files)",
- "multipartArrayWithHttpInfo(java.util.Collection files)",
+ "multipartArray(java.util.Collection files)",
+ "multipartArrayWithHttpInfo(java.util.Collection files)",
"formParams.addAll(\"files\", files.stream().collect(Collectors.toList()));",
//mixed
- "multipartMixed(org.springframework.core.io.Resource file, MultipartMixedMarker marker)",
- "multipartMixedWithHttpInfo(org.springframework.core.io.Resource file, MultipartMixedMarker marker)",
+ "multipartMixed(org.springframework.web.multipart.MultipartFile file, MultipartMixedMarker marker)",
+ "multipartMixedWithHttpInfo(org.springframework.web.multipart.MultipartFile file, MultipartMixedMarker marker)",
"formParams.add(\"file\", file);",
//single file
- "multipartSingle(org.springframework.core.io.Resource file)",
- "multipartSingleWithHttpInfo(org.springframework.core.io.Resource file)",
+ "multipartSingle(org.springframework.web.multipart.MultipartFile file)",
+ "multipartSingleWithHttpInfo(org.springframework.web.multipart.MultipartFile file)",
"formParams.add(\"file\", file);"
);
}
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java
index b77afc858f9..dc3bceaa435 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java
@@ -1,9 +1,14 @@
package org.openapitools.codegen.kotlin.spring;
import com.google.common.collect.testing.Helpers;
-
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.servers.Server;
import org.apache.commons.io.FileUtils;
-import org.openapitools.codegen.*;
+import org.openapitools.codegen.ClientOptInput;
+import org.openapitools.codegen.CodegenConstants;
+import org.openapitools.codegen.DefaultGenerator;
+import org.openapitools.codegen.TestUtils;
import org.openapitools.codegen.kotlin.KotlinTestUtils;
import org.openapitools.codegen.languages.KotlinSpringServerCodegen;
import org.testng.Assert;
@@ -11,12 +16,12 @@ import org.testng.annotations.Test;
import java.io.File;
import java.nio.file.Files;
+import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
-import io.swagger.v3.oas.models.OpenAPI;
-import io.swagger.v3.oas.models.info.Info;
-import io.swagger.v3.oas.models.servers.Server;
+import static org.openapitools.codegen.TestUtils.assertFileContains;
+import static org.openapitools.codegen.TestUtils.assertFileNotContains;
public class KotlinSpringServerCodegenTest {
@@ -203,4 +208,49 @@ public class KotlinSpringServerCodegenTest {
new File(output, "src/main/kotlin/org/openapitools/api/TestV2ApiDelegate.kt")
);
}
+
+ @Test(description = "test delegate reactive with tags")
+ public void delegateReactiveWithTags() throws Exception {
+ File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); //may be move to /build
+ KotlinSpringServerCodegen codegen = new KotlinSpringServerCodegen();
+ codegen.setOutputDir(output.getAbsolutePath());
+ codegen.additionalProperties().put(KotlinSpringServerCodegen.DELEGATE_PATTERN, true);
+ codegen.additionalProperties().put(KotlinSpringServerCodegen.REACTIVE, true);
+ codegen.additionalProperties().put(KotlinSpringServerCodegen.USE_TAGS, true);
+
+ List files = new DefaultGenerator()
+ .opts(
+ new ClientOptInput()
+ .openAPI(TestUtils.parseSpec("src/test/resources/3_0/kotlin/issue7325-use-delegate-reactive-tags-kotlin.yaml"))
+ .config(codegen)
+ )
+ .generate();
+
+ Helpers.assertContainsAllOf(files,
+ new File(output, "src/main/kotlin/org/openapitools/api/TestV1Api.kt"),
+ new File(output, "src/main/kotlin/org/openapitools/api/TestV1ApiController.kt"),
+ new File(output, "src/main/kotlin/org/openapitools/api/TestV1ApiDelegate.kt"),
+ new File(output, "src/main/kotlin/org/openapitools/api/TestV2Api.kt"),
+ new File(output, "src/main/kotlin/org/openapitools/api/TestV2ApiController.kt"),
+ new File(output, "src/main/kotlin/org/openapitools/api/TestV2ApiDelegate.kt")
+ );
+
+ assertFileContains(Paths.get(output + "/src/main/kotlin/org/openapitools/api/TestV1Api.kt"),
+ "suspend fun");
+ assertFileNotContains(Paths.get(output + "/src/main/kotlin/org/openapitools/api/TestV1Api.kt"),
+ "exchange");
+ assertFileContains(Paths.get(output + "/src/main/kotlin/org/openapitools/api/TestV1ApiDelegate.kt"),
+ "suspend fun");
+ assertFileNotContains(Paths.get(output + "/src/main/kotlin/org/openapitools/api/TestV1ApiDelegate.kt"),
+ "ApiUtil");
+
+ assertFileContains(Paths.get(output + "/src/main/kotlin/org/openapitools/api/TestV2Api.kt"),
+ "import kotlinx.coroutines.flow.Flow", "ResponseEntity>");
+ assertFileNotContains(Paths.get(output + "/src/main/kotlin/org/openapitools/api/TestV2Api.kt"),
+ "exchange");
+ assertFileContains(Paths.get(output + "/src/main/kotlin/org/openapitools/api/TestV2ApiDelegate.kt"),
+ "import kotlinx.coroutines.flow.Flow");
+ assertFileNotContains(Paths.get(output + "/src/main/kotlin/org/openapitools/api/TestV2ApiDelegate.kt"),
+ "suspend fun", "ApiUtil");
+ }
}
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PythonClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PythonClientOptionsProvider.java
index 7beb3ec69c0..fc7d74074dd 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PythonClientOptionsProvider.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PythonClientOptionsProvider.java
@@ -19,7 +19,7 @@ package org.openapitools.codegen.options;
import com.google.common.collect.ImmutableMap;
import org.openapitools.codegen.CodegenConstants;
-import org.openapitools.codegen.languages.PythonLegacyClientCodegen;
+import org.openapitools.codegen.languages.PythonClientCodegen;
import java.util.Map;
@@ -30,6 +30,8 @@ public class PythonClientOptionsProvider implements OptionsProvider {
public static final String PACKAGE_URL_VALUE = "";
public static final String USE_NOSE_VALUE = "false";
public static final String RECURSION_LIMIT = "1200";
+ public static final String DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT = "false";
+ public static final String PYTHON_ATTR_NONE_IF_UNSET = "false";
@Override
public String getLanguage() {
@@ -39,16 +41,17 @@ public class PythonClientOptionsProvider implements OptionsProvider {
@Override
public Map createOptions() {
ImmutableMap.Builder builder = new ImmutableMap.Builder();
- return builder.put(PythonLegacyClientCodegen.PACKAGE_URL, PACKAGE_URL_VALUE)
+ return builder.put(PythonClientCodegen.PACKAGE_URL, PACKAGE_URL_VALUE)
.put(CodegenConstants.PACKAGE_NAME, PACKAGE_NAME_VALUE)
.put(CodegenConstants.PROJECT_NAME, PROJECT_NAME_VALUE)
.put(CodegenConstants.PACKAGE_VERSION, PACKAGE_VERSION_VALUE)
- .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, "true")
.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "true")
.put(CodegenConstants.SOURCECODEONLY_GENERATION, "false")
.put(CodegenConstants.LIBRARY, "urllib3")
- .put(PythonLegacyClientCodegen.USE_NOSE, USE_NOSE_VALUE)
- .put(PythonLegacyClientCodegen.RECURSION_LIMIT, RECURSION_LIMIT)
+ .put(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT, DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT)
+ .put(PythonClientCodegen.USE_NOSE, USE_NOSE_VALUE)
+ .put(PythonClientCodegen.RECURSION_LIMIT, RECURSION_LIMIT)
+ .put(PythonClientCodegen.PYTHON_ATTR_NONE_IF_UNSET, PYTHON_ATTR_NONE_IF_UNSET)
.build();
}
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PythonLegacyClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PythonLegacyClientOptionsProvider.java
new file mode 100644
index 00000000000..90e76caea16
--- /dev/null
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PythonLegacyClientOptionsProvider.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
+ * Copyright 2018 SmartBear Software
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openapitools.codegen.options;
+
+import com.google.common.collect.ImmutableMap;
+import org.openapitools.codegen.CodegenConstants;
+import org.openapitools.codegen.languages.PythonLegacyClientCodegen;
+
+import java.util.Map;
+
+public class PythonLegacyClientOptionsProvider implements OptionsProvider {
+ public static final String PACKAGE_NAME_VALUE = "swagger_client_python";
+ public static final String PROJECT_NAME_VALUE = "swagger-client-python";
+ public static final String PACKAGE_VERSION_VALUE = "1.0.0-SNAPSHOT";
+ public static final String PACKAGE_URL_VALUE = "";
+ public static final String USE_NOSE_VALUE = "false";
+ public static final String RECURSION_LIMIT = "1200";
+
+ @Override
+ public String getLanguage() {
+ return "python";
+ }
+
+ @Override
+ public Map createOptions() {
+ ImmutableMap.Builder builder = new ImmutableMap.Builder();
+ return builder.put(PythonLegacyClientCodegen.PACKAGE_URL, PACKAGE_URL_VALUE)
+ .put(CodegenConstants.PACKAGE_NAME, PACKAGE_NAME_VALUE)
+ .put(CodegenConstants.PROJECT_NAME, PROJECT_NAME_VALUE)
+ .put(CodegenConstants.PACKAGE_VERSION, PACKAGE_VERSION_VALUE)
+ .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, "true")
+ .put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "true")
+ .put(CodegenConstants.SOURCECODEONLY_GENERATION, "false")
+ .put(CodegenConstants.LIBRARY, "urllib3")
+ .put(PythonLegacyClientCodegen.USE_NOSE, USE_NOSE_VALUE)
+ .put(PythonLegacyClientCodegen.RECURSION_LIMIT, RECURSION_LIMIT)
+ .build();
+ }
+
+ @Override
+ public boolean isServer() {
+ return false;
+ }
+}
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift5OptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift5OptionsProvider.java
index e432b326d1c..9e2a4a3b36f 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift5OptionsProvider.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift5OptionsProvider.java
@@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableMap;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.languages.Swift5ClientCodegen;
+import java.io.File;
import java.util.Map;
public class Swift5OptionsProvider implements OptionsProvider {
@@ -45,9 +46,12 @@ public class Swift5OptionsProvider implements OptionsProvider {
public static final String POD_DOCUMENTATION_URL_VALUE = "podDocumentationURL";
public static final String READONLY_PROPERTIES_VALUE = "false";
public static final String SWIFT_USE_API_NAMESPACE_VALUE = "swiftUseApiNamespace";
+ public static final String USE_BACKTICKS_ESCAPES_VALUE = "false";
public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false";
public static final String PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = "true";
public static final String LIBRARY_VALUE = "alamofire";
+ public static final String USE_SPM_FILE_STRUCTURE_VALUE = "false";
+ public static final String SWIFT_PACKAGE_PATH_VALUE = "";
@Override
public String getLanguage() {
@@ -77,6 +81,7 @@ public class Swift5OptionsProvider implements OptionsProvider {
.put(Swift5ClientCodegen.POD_DOCUMENTATION_URL, POD_DOCUMENTATION_URL_VALUE)
.put(Swift5ClientCodegen.READONLY_PROPERTIES, READONLY_PROPERTIES_VALUE)
.put(Swift5ClientCodegen.SWIFT_USE_API_NAMESPACE, SWIFT_USE_API_NAMESPACE_VALUE)
+ .put(Swift5ClientCodegen.USE_BACKTICK_ESCAPES, USE_BACKTICKS_ESCAPES_VALUE)
.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "true")
.put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE)
.put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, PREPEND_FORM_OR_BODY_PARAMETERS_VALUE)
@@ -84,6 +89,8 @@ public class Swift5OptionsProvider implements OptionsProvider {
.put(CodegenConstants.LIBRARY, LIBRARY_VALUE)
.put(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "true")
.put(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT, "true")
+ .put(Swift5ClientCodegen.USE_SPM_FILE_STRUCTURE, USE_SPM_FILE_STRUCTURE_VALUE)
+ .put(Swift5ClientCodegen.SWIFT_PACKAGE_PATH, SWIFT_PACKAGE_PATH_VALUE)
.build();
}
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonClientOptionsTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonClientOptionsTest.java
index 8bec98892ef..e423c6e8584 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonClientOptionsTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonClientOptionsTest.java
@@ -19,7 +19,7 @@ package org.openapitools.codegen.python;
import org.openapitools.codegen.AbstractOptionsTest;
import org.openapitools.codegen.CodegenConfig;
-import org.openapitools.codegen.languages.PythonLegacyClientCodegen;
+import org.openapitools.codegen.languages.PythonClientCodegen;
import org.openapitools.codegen.options.PythonClientOptionsProvider;
import org.testng.Assert;
@@ -29,7 +29,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
public class PythonClientOptionsTest extends AbstractOptionsTest {
- private PythonLegacyClientCodegen clientCodegen = mock(PythonLegacyClientCodegen.class, mockSettings);
+ private PythonClientCodegen clientCodegen = mock(PythonClientCodegen.class, mockSettings);
public PythonClientOptionsTest() {
super(new PythonClientOptionsProvider());
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonClientTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonClientTest.java
index 4face161d7e..842d6a2851a 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonClientTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonClientTest.java
@@ -460,7 +460,7 @@ public class PythonClientTest {
expectedValue = expectedValue.replaceAll("\\r\\n", "\n");
- Assert.assertEquals(expectedValue.trim(), exampleValue.trim());
+ Assert.assertEquals(exampleValue.trim(), expectedValue.trim());
}
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonLegacyClientOptionsTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonLegacyClientOptionsTest.java
new file mode 100644
index 00000000000..8c17cdbb2fd
--- /dev/null
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonLegacyClientOptionsTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
+ * Copyright 2018 SmartBear Software
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openapitools.codegen.python;
+
+import org.openapitools.codegen.AbstractOptionsTest;
+import org.openapitools.codegen.CodegenConfig;
+import org.openapitools.codegen.languages.PythonLegacyClientCodegen;
+import org.openapitools.codegen.options.PythonLegacyClientOptionsProvider;
+import org.testng.Assert;
+
+import java.io.File;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class PythonLegacyClientOptionsTest extends AbstractOptionsTest {
+ private PythonLegacyClientCodegen clientCodegen = mock(PythonLegacyClientCodegen.class, mockSettings);
+
+ public PythonLegacyClientOptionsTest() {
+ super(new PythonLegacyClientOptionsProvider());
+ }
+
+ @Override
+ protected CodegenConfig getCodegenConfig() {
+ return clientCodegen;
+ }
+
+ @SuppressWarnings("unused")
+ @Override
+ protected void verifyOptions() {
+ Assert.assertEquals(clientCodegen.packagePath(), PythonLegacyClientOptionsProvider.PACKAGE_NAME_VALUE.replace('.', File.separatorChar));
+
+ verify(clientCodegen).setPackageName(PythonLegacyClientOptionsProvider.PACKAGE_NAME_VALUE);
+ verify(clientCodegen).setProjectName(PythonLegacyClientOptionsProvider.PROJECT_NAME_VALUE);
+ verify(clientCodegen).setPackageVersion(PythonLegacyClientOptionsProvider.PACKAGE_VERSION_VALUE);
+ verify(clientCodegen).setPackageUrl(PythonLegacyClientOptionsProvider.PACKAGE_URL_VALUE);
+ verify(clientCodegen).setUseNose(PythonLegacyClientOptionsProvider.USE_NOSE_VALUE);
+ }
+}
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java
index 3981f3f6078..f50f20ac135 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java
@@ -677,4 +677,29 @@ public class RubyClientCodegenTest {
// pattern_dont_escape_backslash '/^pattern\d{3}$/i' NOTE: the double \ is to escape \ in string but is read as single \
Assert.assertEquals(op.allParams.get(2).pattern, "/^pattern\\d{3}$/i");
}
+
+ /**
+ * We want to make sure that the type mapping works as expect
+ */
+ @Test(description = "test type mapping to handle special format, e.g. string+special")
+ public void typeMappingTest() {
+ final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/type_mapping_test.yaml");
+ final RubyClientCodegen codegen = new RubyClientCodegen();
+ codegen.typeMapping().put("string+special", "VerySpecialStringInRuby");
+
+ codegen.setOpenAPI(openAPI);
+ final String path = "/animals";
+ final Operation p = openAPI.getPaths().get(path).getGet();
+ final CodegenOperation op = codegen.fromOperation(path, "get", p, null);
+ Assert.assertEquals(op.allParams.get(0).dataType, "VerySpecialStringInRuby");
+
+ final Schema schema = openAPI.getComponents().getSchemas().get("Animal");
+ codegen.setOpenAPI(openAPI);
+ CodegenModel animal = codegen.fromModel("Animal", schema);
+ Assert.assertNotNull(animal);
+ CodegenProperty cp2 = animal.getVars().get(2);
+ Assert.assertEquals(cp2.name, "mapping_test");
+ Assert.assertFalse(cp2.required);
+ Assert.assertEquals(cp2.dataType, "VerySpecialStringInRuby");
+ }
}
diff --git a/modules/openapi-generator/src/test/resources/2_0/python-client-experimental/petstore-with-fake-endpoints-models-for-testing.yaml b/modules/openapi-generator/src/test/resources/2_0/python-client-experimental/petstore-with-fake-endpoints-models-for-testing.yaml
index 9e9451dcc5b..097ae6768bb 100644
--- a/modules/openapi-generator/src/test/resources/2_0/python-client-experimental/petstore-with-fake-endpoints-models-for-testing.yaml
+++ b/modules/openapi-generator/src/test/resources/2_0/python-client-experimental/petstore-with-fake-endpoints-models-for-testing.yaml
@@ -1373,8 +1373,6 @@ definitions:
properties:
breed:
type: string
- additionalProperties: false
- additionalProperties: false
Cat:
allOf:
- $ref: '#/definitions/Animal'
@@ -1523,8 +1521,7 @@ definitions:
type: object
additionalProperties:
type: array
- items:
- type: object
+ items: {}
map_map_string:
type: object
additionalProperties:
@@ -1535,14 +1532,15 @@ definitions:
type: object
additionalProperties:
type: object
- additionalProperties:
- type: object
- anytype_1:
- type: object
- anytype_2: {}
+ additionalProperties: {}
+ anytype_1: {}
+ anytype_2:
+ description: no type is set for this
anytype_3:
type: object
properties: {}
+ description: 'because of a bug in swagger-parser, this should have values {str: (str, int, float...)}
+ but instead we get any type. See https://github.com/swagger-api/swagger-parser/issues/1378'
AdditionalPropertiesString:
type: object
properties:
@@ -2091,7 +2089,6 @@ definitions:
properties:
interNet:
type: boolean
- additionalProperties: false
GrandparentAnimal:
type: object
required:
diff --git a/modules/openapi-generator/src/test/resources/2_0/swift/petstore-with-fake-endpoints-models-for-testing.yaml b/modules/openapi-generator/src/test/resources/2_0/swift/petstore-with-fake-endpoints-models-for-testing.yaml
index c37f4329e4e..38797a5bf10 100644
--- a/modules/openapi-generator/src/test/resources/2_0/swift/petstore-with-fake-endpoints-models-for-testing.yaml
+++ b/modules/openapi-generator/src/test/resources/2_0/swift/petstore-with-fake-endpoints-models-for-testing.yaml
@@ -1086,7 +1086,6 @@ definitions:
xml:
name: Order
Category:
- x-swift-hashable: true
type: object
required:
- name
@@ -1097,6 +1096,7 @@ definitions:
name:
type: string
default: default-name
+ x-nullable: true
xml:
name: Category
User:
diff --git a/modules/openapi-generator/src/test/resources/2_0/templates/Java/ApiClient.mustache b/modules/openapi-generator/src/test/resources/2_0/templates/Java/ApiClient.mustache
index 116f14c8650..d75e455961c 100644
--- a/modules/openapi-generator/src/test/resources/2_0/templates/Java/ApiClient.mustache
+++ b/modules/openapi-generator/src/test/resources/2_0/templates/Java/ApiClient.mustache
@@ -1,28 +1,38 @@
-//overloaded main template file to add this comment
-
{{>licenseInfo}}
package {{invokerPackage}};
+{{#threetenbp}}
+import org.threeten.bp.*;
+
+{{/threetenbp}}
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
+{{#joda}}
+import com.fasterxml.jackson.datatype.joda.JodaModule;
+{{/joda}}
{{#java8}}
-import com.fasterxml.jackson.datatype.jsr310.*;
-{{/java8}}
-{{^java8}}
-import com.fasterxml.jackson.datatype.joda.*;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+{{^threetenbp}}
+import java.time.OffsetDateTime;
+{{/threetenbp}}
{{/java8}}
+{{#threetenbp}}
+import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule;
+{{/threetenbp}}
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.api.client.filter.GZIPContentEncodingFilter;
import com.sun.jersey.api.client.filter.LoggingFilter;
import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.multipart.file.FileDataBodyPart;
+import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.Response.Status.Family;
import javax.ws.rs.core.MediaType;
@@ -31,7 +41,9 @@ import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Arrays;
import java.util.ArrayList;
import java.util.Date;
import java.util.TimeZone;
@@ -44,14 +56,51 @@ import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import {{invokerPackage}}.auth.Authentication;
+{{#hasHttpBasicMethods}}
import {{invokerPackage}}.auth.HttpBasicAuth;
+{{/hasHttpBasicMethods}}
+{{#hasHttpBearerMethods}}
+import {{invokerPackage}}.auth.HttpBearerAuth;
+{{/hasHttpBearerMethods}}
+{{#hasApiKeyMethods}}
import {{invokerPackage}}.auth.ApiKeyAuth;
+{{/hasApiKeyMethods}}
+{{#hasOAuthMethods}}
import {{invokerPackage}}.auth.OAuth;
+{{/hasOAuthMethods}}
{{>generatedAnnotation}}
-public class ApiClient {
+public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
private Map defaultHeaderMap = new HashMap();
- private String basePath = "{{basePath}}";
+ private Map defaultCookieMap = new HashMap();
+ private String basePath = "{{{basePath}}}";
+ protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList(
+{{/-first}} new ServerConfiguration(
+ "{{{url}}}",
+ "{{{description}}}{{^description}}No description provided{{/description}}",
+ new HashMap(){{#variables}}{{#-first}} {{
+{{/-first}} put("{{{name}}}", new ServerVariable(
+ "{{{description}}}{{^description}}No description provided{{/description}}",
+ "{{{defaultValue}}}",
+ new HashSet(
+ {{#enumValues}}
+ {{#-first}}
+ Arrays.asList(
+ {{/-first}}
+ "{{{.}}}"{{^-last}},{{/-last}}
+ {{#-last}}
+ )
+ {{/-last}}
+ {{/enumValues}}
+ )
+ ));
+ {{#-last}}
+ }}{{/-last}}{{/variables}}
+ ){{^-last}},{{/-last}}
+ {{#-last}}
+ ){{/-last}}{{/servers}});
+ protected Integer serverIndex = 0;
+ protected Map serverVariables = null;
private boolean debugging = false;
private int connectionTimeout = 0;
@@ -69,15 +118,23 @@ public class ApiClient {
objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
+ {{#joda}}
+ objectMapper.registerModule(new JodaModule());
+ {{/joda}}
{{#java8}}
objectMapper.registerModule(new JavaTimeModule());
{{/java8}}
- {{^java8}}
- objectMapper.registerModule(new JodaModule());
- {{/java8}}
+ {{#threetenbp}}
+ ThreeTenModule module = new ThreeTenModule();
+ module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT);
+ module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME);
+ module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME);
+ objectMapper.registerModule(module);
+ {{/threetenbp}}
objectMapper.setDateFormat(ApiClient.buildDefaultDateFormat());
dateFormat = ApiClient.buildDefaultDateFormat();
@@ -86,8 +143,9 @@ public class ApiClient {
setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}");
// Setup authentications (key: authentication name, value: authentication).
- authentications = new HashMap();{{#authMethods}}{{#isBasic}}
- authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}}
+ authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}}
+ authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}}
+ authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}}
authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}}
authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}}
// Prevent the authentications from being modified.
@@ -112,6 +170,7 @@ public class ApiClient {
DefaultClientConfig conf = new DefaultClientConfig();
conf.getSingletons().add(jsonProvider);
Client client = Client.create(conf);
+ client.addFilter(new GZIPContentEncodingFilter({{#useGzipFeature}}true{{/useGzipFeature}}{{^useGzipFeature}}false{{/useGzipFeature}}));
if (debugging) {
client.addFilter(new LoggingFilter());
}
@@ -156,6 +215,33 @@ public class ApiClient {
return this;
}
+ public List getServers() {
+ return servers;
+ }
+
+ public ApiClient setServers(List servers) {
+ this.servers = servers;
+ return this;
+ }
+
+ public Integer getServerIndex() {
+ return serverIndex;
+ }
+
+ public ApiClient setServerIndex(Integer serverIndex) {
+ this.serverIndex = serverIndex;
+ return this;
+ }
+
+ public Map getServerVariables() {
+ return serverVariables;
+ }
+
+ public ApiClient setServerVariables(Map serverVariables) {
+ this.serverVariables = serverVariables;
+ return this;
+ }
+
/**
* Gets the status code of the previous request
* @return Status code
@@ -190,6 +276,24 @@ public class ApiClient {
return authentications.get(authName);
}
+ {{#hasHttpBearerMethods}}
+ /**
+ * Helper method to set access token for the first Bearer authentication.
+ * @param bearerToken Bearer token
+ */
+ public void setBearerToken(String bearerToken) {
+ for (Authentication auth : authentications.values()) {
+ if (auth instanceof HttpBearerAuth) {
+ ((HttpBearerAuth) auth).setBearerToken(bearerToken);
+ return;
+ }
+ }
+ throw new RuntimeException("No Bearer authentication configured!");
+ }
+
+ {{/hasHttpBearerMethods}}
+
+ {{#hasHttpBasicMethods}}
/**
* Helper method to set username for the first HTTP basic authentication.
* @param username Username
@@ -218,9 +322,12 @@ public class ApiClient {
throw new RuntimeException("No HTTP basic authentication configured!");
}
+ {{/hasHttpBasicMethods}}
+
+ {{#hasApiKeyMethods}}
/**
* Helper method to set API key value for the first API key authentication.
- * @param apiKey API key
+ * @param apiKey the API key
*/
public void setApiKey(String apiKey) {
for (Authentication auth : authentications.values()) {
@@ -246,6 +353,9 @@ public class ApiClient {
throw new RuntimeException("No API key authentication configured!");
}
+ {{/hasApiKeyMethods}}
+
+ {{#hasOAuthMethods}}
/**
* Helper method to set access token for the first OAuth2 authentication.
* @param accessToken Access token
@@ -260,6 +370,8 @@ public class ApiClient {
throw new RuntimeException("No OAuth2 authentication configured!");
}
+ {{/hasOAuthMethods}}
+
/**
* Set the User-Agent header's value (by adding to the default header map).
* @param userAgent User agent
@@ -282,6 +394,18 @@ public class ApiClient {
return this;
}
+ /**
+ * Add a default cookie.
+ *
+ * @param key The cookie's key
+ * @param value The cookie's value
+ * @return API client
+ */
+ public ApiClient addDefaultCookie(String key, String value) {
+ defaultCookieMap.put(key, value);
+ return this;
+ }
+
/**
* Check that whether debugging is enabled for this API client.
* @return True if debugging is on
@@ -378,7 +502,9 @@ public class ApiClient {
return "";
} else if (param instanceof Date) {
return formatDate((Date) param);
- } else if (param instanceof Collection) {
+ } {{#jsr310}}else if (param instanceof OffsetDateTime) {
+ return formatOffsetDateTime((OffsetDateTime) param);
+ } {{/jsr310}}else if (param instanceof Collection) {
StringBuilder b = new StringBuilder();
for(Object o : (Collection>)param) {
if(b.length() > 0) {
@@ -392,62 +518,71 @@ public class ApiClient {
}
}
- /*
- * Format to {@code Pair} objects.
- * @param collectionFormat Collection format
- * @param name Name
- * @param value Value
- * @return List of pair
+ /**
+ * Formats the specified query parameter to a list containing a single {@code Pair} object.
+ *
+ * Note that {@code value} must not be a collection.
+ *
+ * @param name The name of the parameter.
+ * @param value The value of the parameter.
+ * @return A list containing a single {@code Pair} object.
*/
- public List parameterToPairs(String collectionFormat, String name, Object value){
+ public List parameterToPair(String name, Object value) {
List params = new ArrayList();
// preconditions
- if (name == null || name.isEmpty() || value == null) return params;
+ if (name == null || name.isEmpty() || value == null || value instanceof Collection) return params;
- Collection> valueCollection;
- if (value instanceof Collection>) {
- valueCollection = (Collection>) value;
- } else {
- params.add(new Pair(name, parameterToString(value)));
+ params.add(new Pair(name, parameterToString(value)));
+ return params;
+ }
+
+ /**
+ * Formats the specified collection query parameters to a list of {@code Pair} objects.
+ *
+ * Note that the values of each of the returned Pair objects are percent-encoded.
+ *
+ * @param collectionFormat The collection format of the parameter.
+ * @param name The name of the parameter.
+ * @param value The value of the parameter.
+ * @return A list of {@code Pair} objects.
+ */
+ public List parameterToPairs(String collectionFormat, String name, Collection value) {
+ List params = new ArrayList();
+
+ // preconditions
+ if (name == null || name.isEmpty() || value == null) {
return params;
}
- if (valueCollection.isEmpty()){
- return params;
- }
-
- // get the collection format
- String format = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); // default: csv
-
// create the params based on the collection format
- if ("multi".equals(format)) {
- for (Object item : valueCollection) {
- params.add(new Pair(name, parameterToString(item)));
+ if ("multi".equals(collectionFormat)) {
+ for (Object item : value) {
+ params.add(new Pair(name, escapeString(parameterToString(item))));
}
-
return params;
}
+ // collectionFormat is assumed to be "csv" by default
String delimiter = ",";
- if ("csv".equals(format)) {
- delimiter = ",";
- } else if ("ssv".equals(format)) {
- delimiter = " ";
- } else if ("tsv".equals(format)) {
- delimiter = "\t";
- } else if ("pipes".equals(format)) {
- delimiter = "|";
+ // escape all delimiters except commas, which are URI reserved
+ // characters
+ if ("ssv".equals(collectionFormat)) {
+ delimiter = escapeString(" ");
+ } else if ("tsv".equals(collectionFormat)) {
+ delimiter = escapeString("\t");
+ } else if ("pipes".equals(collectionFormat)) {
+ delimiter = escapeString("|");
}
StringBuilder sb = new StringBuilder() ;
- for (Object item : valueCollection) {
+ for (Object item : value) {
sb.append(delimiter);
- sb.append(parameterToString(item));
+ sb.append(escapeString(parameterToString(item)));
}
- params.add(new Pair(name, sb.substring(1)));
+ params.add(new Pair(name, sb.substring(delimiter.length())));
return params;
}
@@ -458,11 +593,13 @@ public class ApiClient {
* application/json
* application/json; charset=UTF8
* APPLICATION/JSON
+ * application/vnd.company+json
* @param mime MIME
* @return True if MIME type is boolean
*/
public boolean isJsonMime(String mime) {
- return mime != null && mime.matches("(?i)application\\/json(;.*)?");
+ String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$";
+ return mime != null && (mime.matches(jsonMime) || mime.equals("*/*"));
}
/**
@@ -493,10 +630,10 @@ public class ApiClient {
*
* @param contentTypes The Content-Type array to select from
* @return The Content-Type header to use. If the given array is empty,
- * JSON will be used.
+ * or matches "any", JSON will be used.
*/
public String selectHeaderContentType(String[] contentTypes) {
- if (contentTypes.length == 0) {
+ if (contentTypes.length == 0 || contentTypes[0].equals("*/*")) {
return "application/json";
}
for (String contentType : contentTypes) {
@@ -561,11 +698,24 @@ public class ApiClient {
*
* @param path The sub path
* @param queryParams The query parameters
+ * @param collectionQueryParams The collection query parameters
* @return The full URL
*/
- private String buildUrl(String path, List queryParams) {
+ private String buildUrl(String path, List