Compare commits

..

42 Commits

Author SHA1 Message Date
William Cheng
a3fb9aeef8 Fix HTML entity encoding in plugins documentation 2026-02-03 13:22:48 +08:00
dersvenhesse
7c5f7cf4e5 docs: update useSpringBoot3 note (#22881)
* docs: update useSpringBoot3 note

* chore: moved changes to code classes

* docs: add generated docs

* docs: update java-camel

* docs: ecape ≥
2026-02-03 13:08:48 +08:00
Rens Groothuijsen
2ab70fa46b fix(typescript-axios): Ignore unused parameter on JSON serializer replacer function (#22858) 2026-02-03 13:08:08 +08:00
Pierre Segalen
95911180f6 Fixed TypeScript code generation for oneOf using arrays (#22780) 2026-02-02 13:20:48 +01:00
George Holderness
1cafc1673a fix: apply integer type fitting for Rust params (#22853)
We already have logic in postProcessModelProperty to fit integer
parameters into the correct Rust primitives. However, this doesn't apply
to other kinds of parameters so integer-typed parameters which end up in
function calls for Api traits in lib.rs are always i32, even when this
is improper.

This commit refactors integer type fitting so that we can run it on both
processParam and model post-processing.
2026-02-02 19:53:10 +08:00
dsteeley
268213004e feat: Support selective ssl/tls backend in rust-server to optionally remove openssl (#22825)
* feat: Support selective ssl/tls backend in rust-server to avoid always requiring openssl

* feat: Switch default features so a user must select SSL backend

* Further tweaks to rust-server HTTPS feature flagging
2026-02-02 17:58:32 +08:00
William Cheng
ad2044c581 minor fix using jackson check (#22877) 2026-02-02 17:40:07 +08:00
William Cheng
f3a21a8bba update samples 2026-02-02 16:33:22 +08:00
Luís Cabral
811529cb66 Fix Jackson Serialization of additionalProperties on java and jaxrs-spec (#22366) 2026-02-02 15:47:11 +08:00
dependabot[bot]
883bd56ea9 build(deps): bump diff and mocha (#22875)
Bumps [diff](https://github.com/kpdecker/jsdiff) to 3.5.1 and updates ancestor dependency [mocha](https://github.com/mochajs/mocha). These dependencies need to be updated together.


Updates `diff` from 3.5.0 to 3.5.1
- [Changelog](https://github.com/kpdecker/jsdiff/blob/master/release-notes.md)
- [Commits](https://github.com/kpdecker/jsdiff/compare/v3.5.0...v3.5.1)

Updates `mocha` from 5.2.0 to 11.7.5
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/v11.7.5/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v5.2.0...v11.7.5)

---
updated-dependencies:
- dependency-name: diff
  dependency-version: 3.5.1
  dependency-type: indirect
- dependency-name: mocha
  dependency-version: 11.7.5
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-02 15:38:31 +08:00
William Cheng
897590ae6a update undici to newer version in typescript generator (#22874) 2026-02-02 15:26:17 +08:00
dependabot[bot]
3c052d8b64 build(deps): bump eslint and rewire (#22872)
Bumps [eslint](https://github.com/eslint/eslint) to 9.39.2 and updates ancestor dependency [rewire](https://github.com/jhnns/rewire). These dependencies need to be updated together.


Updates `eslint` from 4.19.1 to 9.39.2
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v4.19.1...v9.39.2)

Updates `rewire` from 4.0.1 to 9.0.1
- [Release notes](https://github.com/jhnns/rewire/releases)
- [Changelog](https://github.com/jhnns/rewire/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jhnns/rewire/compare/v4.0.1...v9.0.1)

---
updated-dependencies:
- dependency-name: eslint
  dependency-version: 9.39.2
  dependency-type: indirect
- dependency-name: rewire
  dependency-version: 9.0.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-02 14:49:58 +08:00
dependabot[bot]
34dc09b676 build(deps-dev): bump tar (#22873)
Bumps [tar](https://github.com/isaacs/node-tar) from 7.5.6 to 7.5.7.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v7.5.6...v7.5.7)

---
updated-dependencies:
- dependency-name: tar
  dependency-version: 7.5.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-02 14:49:08 +08:00
dependabot[bot]
f8e1fadf4e build(deps): bump diff and mocha (#22857)
Bumps [diff](https://github.com/kpdecker/jsdiff) to 3.5.1 and updates ancestor dependency [mocha](https://github.com/mochajs/mocha). These dependencies need to be updated together.


Updates `diff` from 3.2.0 to 3.5.1
- [Changelog](https://github.com/kpdecker/jsdiff/blob/master/release-notes.md)
- [Commits](https://github.com/kpdecker/jsdiff/compare/v3.2.0...v3.5.1)

Updates `mocha` from 3.5.3 to 11.7.5
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/v11.7.5/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v3.5.3...v11.7.5)

---
updated-dependencies:
- dependency-name: diff
  dependency-version: 3.5.1
  dependency-type: indirect
- dependency-name: mocha
  dependency-version: 11.7.5
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-02 14:48:45 +08:00
William Cheng
41a8573437 remove compiler option from ts fetch test (#22871) 2026-02-02 13:44:35 +08:00
Bruno Coelho
fd17603109 [Kotlin][Client] Migrate Enum.values() to Enum.entities (#22852) 2026-02-02 11:57:12 +08:00
William Cheng
7506b6ca02 add defaultToEmptyContainer option to java generators (#22869) 2026-02-02 00:27:01 +08:00
dependabot[bot]
3df34f6aab build(deps): bump diff and mocha (#22868)
Bumps [diff](https://github.com/kpdecker/jsdiff) to 4.0.4 and updates ancestor dependency [mocha](https://github.com/mochajs/mocha). These dependencies need to be updated together.


Updates `diff` from 4.0.2 to 4.0.4
- [Changelog](https://github.com/kpdecker/jsdiff/blob/master/release-notes.md)
- [Commits](https://github.com/kpdecker/jsdiff/compare/v4.0.2...v4.0.4)

Updates `mocha` from 10.2.0 to 10.8.2
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v10.2.0...v10.8.2)

---
updated-dependencies:
- dependency-name: diff
  dependency-version: 4.0.4
  dependency-type: indirect
- dependency-name: mocha
  dependency-version: 10.8.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-01 16:06:04 +08:00
Jachym Metlicka
95e8360c19 [KOTLIN-CLIENT] fix Parent interface class having incorrect collection property type List instead of Set (#22850)
* fix issue #22696

* reduce unnecessary repetition in mustache schema

* add unit tests & regenerate files

* regenerate files
2026-02-01 15:11:56 +08:00
dependabot[bot]
ba8327386c build(deps-dev): bump tar in /samples/client/others/typescript-angular (#22866)
Bumps [tar](https://github.com/isaacs/node-tar) from 7.5.3 to 7.5.7.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v7.5.3...v7.5.7)

---
updated-dependencies:
- dependency-name: tar
  dependency-version: 7.5.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-01 15:10:19 +08:00
dependabot[bot]
8b6df51cdf build(deps-dev): bump tar (#22865)
Bumps [tar](https://github.com/isaacs/node-tar) from 7.5.5 to 7.5.7.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v7.5.5...v7.5.7)

---
updated-dependencies:
- dependency-name: tar
  dependency-version: 7.5.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-01 00:23:18 +08:00
dependabot[bot]
66a211ec56 build(deps): bump eslint and rewire (#22860)
Bumps [eslint](https://github.com/eslint/eslint) to 9.39.2 and updates ancestor dependency [rewire](https://github.com/jhnns/rewire). These dependencies need to be updated together.


Updates `eslint` from 8.57.1 to 9.39.2
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v8.57.1...v9.39.2)

Updates `rewire` from 7.0.0 to 9.0.1
- [Release notes](https://github.com/jhnns/rewire/releases)
- [Changelog](https://github.com/jhnns/rewire/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jhnns/rewire/compare/v7.0.0...v9.0.1)

---
updated-dependencies:
- dependency-name: eslint
  dependency-version: 9.39.2
  dependency-type: indirect
- dependency-name: rewire
  dependency-version: 9.0.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-31 22:49:12 +08:00
dependabot[bot]
4da2d8095d build(deps): bump eslint and rewire (#22861)
Bumps [eslint](https://github.com/eslint/eslint) to 9.39.2 and updates ancestor dependency [rewire](https://github.com/jhnns/rewire). These dependencies need to be updated together.


Updates `eslint` from 4.19.1 to 9.39.2
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v4.19.1...v9.39.2)

Updates `rewire` from 4.0.1 to 9.0.1
- [Release notes](https://github.com/jhnns/rewire/releases)
- [Changelog](https://github.com/jhnns/rewire/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jhnns/rewire/compare/v4.0.1...v9.0.1)

---
updated-dependencies:
- dependency-name: eslint
  dependency-version: 9.39.2
  dependency-type: indirect
- dependency-name: rewire
  dependency-version: 9.0.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-31 22:49:08 +08:00
dependabot[bot]
d26f67c576 build(deps-dev): bump tar (#22862)
Bumps [tar](https://github.com/isaacs/node-tar) from 7.5.6 to 7.5.7.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v7.5.6...v7.5.7)

---
updated-dependencies:
- dependency-name: tar
  dependency-version: 7.5.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-31 22:49:01 +08:00
dependabot[bot]
63151d3a68 build(deps): bump diff and mocha (#22855)
Bumps [diff](https://github.com/kpdecker/jsdiff) to 3.5.1 and updates ancestor dependency [mocha](https://github.com/mochajs/mocha). These dependencies need to be updated together.


Updates `diff` from 3.5.0 to 3.5.1
- [Changelog](https://github.com/kpdecker/jsdiff/blob/master/release-notes.md)
- [Commits](https://github.com/kpdecker/jsdiff/compare/v3.5.0...v3.5.1)

Updates `mocha` from 5.2.0 to 11.7.5
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/v11.7.5/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v5.2.0...v11.7.5)

---
updated-dependencies:
- dependency-name: diff
  dependency-version: 3.5.1
  dependency-type: indirect
- dependency-name: mocha
  dependency-version: 11.7.5
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-31 16:59:16 +08:00
A. Todisco
6f211a20e8 [Protobuf] Fix Discriminator Issue and add capability Enum Extraction (#22740)
* fix(protobuf-codegen): Fix protobuf import path with discriminator

This PR fixes a critical bug in the protobuf schema generator where models using discriminators with llOf composition were generating invalid import paths when child schemas contained references to other models.

* fix: Add missing element in OpenAPI discriminator test case

* feat(protobuf-generator): Improve protobuf generation

* Improve management of inheritance
* Improve management of discriminator
* Allow to separate inline enums in external files
* Add unit test

* fix: Improve logic when extracting enums to avoid collision in enum values

* fix: Manage case with Enum in lists

* fix: Fix issue on enum extraction

Fix issue linked to enum in array when there is inheritance or discriminator

* doc: Add documentation for new parameter

* chore: Update protobuf samples

---------

Co-authored-by: Anthony TODISCO <Anthony.TODISCO+amadeus@amadeus.com>
2026-01-30 16:42:00 +08:00
Julien
82ad061fe9 [go] Fix text escaping in example code generation (#22841)
Wrap example values with escapeText() to properly escape special
characters in generated Go client code examples

Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-01-30 11:23:49 +08:00
Anderson de Borba
063a780c7a Removed unnecessary cast to HttpClientErrorException as both classes in the catch extend HttpStatusCodeException (#22849) 2026-01-30 10:59:54 +08:00
dependabot[bot]
b4430804c1 build(deps-dev): bump tar (#22845)
Bumps [tar](https://github.com/isaacs/node-tar) from 7.5.6 to 7.5.7.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v7.5.6...v7.5.7)

---
updated-dependencies:
- dependency-name: tar
  dependency-version: 7.5.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-29 12:52:19 +08:00
Matt Pollock
c56ea5557a [R] avoid to-JSON issues when R6 classes contain lists of R6 classes (#22828)
* [R] avoid to-JSON issues when R6 classes contain lists of R6 classes

* fix missing comma

* only include extractor methods when they are needed

* regenerate samples

* fix typo
2026-01-29 12:34:17 +08:00
dependabot[bot]
a625300e3f build(deps-dev): bump hono (#22842)
Bumps [hono](https://github.com/honojs/hono) from 4.11.4 to 4.11.7.
- [Release notes](https://github.com/honojs/hono/releases)
- [Commits](https://github.com/honojs/hono/compare/v4.11.4...v4.11.7)

---
updated-dependencies:
- dependency-name: hono
  dependency-version: 4.11.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-29 12:25:35 +08:00
dependabot[bot]
8b563222bd build(deps-dev): bump hono (#22830)
Bumps [hono](https://github.com/honojs/hono) from 4.11.4 to 4.11.7.
- [Release notes](https://github.com/honojs/hono/releases)
- [Commits](https://github.com/honojs/hono/compare/v4.11.4...v4.11.7)

---
updated-dependencies:
- dependency-name: hono
  dependency-version: 4.11.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-28 18:16:07 +08:00
dependabot[bot]
572b315f8b build(deps-dev): bump hono (#22831)
Bumps [hono](https://github.com/honojs/hono) from 4.11.4 to 4.11.7.
- [Release notes](https://github.com/honojs/hono/releases)
- [Commits](https://github.com/honojs/hono/compare/v4.11.4...v4.11.7)

---
updated-dependencies:
- dependency-name: hono
  dependency-version: 4.11.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-28 18:15:56 +08:00
dependabot[bot]
c5993af2ea build(deps-dev): bump hono in /samples/client/others/typescript-angular (#22833)
Bumps [hono](https://github.com/honojs/hono) from 4.11.4 to 4.11.7.
- [Release notes](https://github.com/honojs/hono/releases)
- [Commits](https://github.com/honojs/hono/compare/v4.11.4...v4.11.7)

---
updated-dependencies:
- dependency-name: hono
  dependency-version: 4.11.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-28 18:15:44 +08:00
scarf
f7ac63a188 feat(normalizer): add SORT_MODEL_PROPERTIES rule for deterministic output (#22836)
Add new OpenAPINormalizer rule SORT_MODEL_PROPERTIES that sorts schema
properties alphabetically by name. This ensures deterministic code
generation output regardless of property ordering in the source spec.

The rule:
- Uses TreeMap to sort properties by natural string order
- Applies at the OpenAPI normalization stage, working for all generators
- Is opt-in (defaults to false) to maintain backward compatibility

Usage:
  openapi-generator generate --openapi-normalizer SORT_MODEL_PROPERTIES=true ...

Fixes non-deterministic property ordering that could cause spurious diffs
in generated code when the source schema order varies.
2026-01-28 17:36:18 +08:00
dependabot[bot]
c0d555ba4a build(deps-dev): bump hono (#22832)
Bumps [hono](https://github.com/honojs/hono) from 4.11.4 to 4.11.7.
- [Release notes](https://github.com/honojs/hono/releases)
- [Commits](https://github.com/honojs/hono/compare/v4.11.4...v4.11.7)

---
updated-dependencies:
- dependency-name: hono
  dependency-version: 4.11.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-28 16:40:27 +08:00
dependabot[bot]
683b024154 build(deps-dev): bump hono (#22834)
Bumps [hono](https://github.com/honojs/hono) from 4.11.4 to 4.11.7.
- [Release notes](https://github.com/honojs/hono/releases)
- [Commits](https://github.com/honojs/hono/compare/v4.11.4...v4.11.7)

---
updated-dependencies:
- dependency-name: hono
  dependency-version: 4.11.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-28 15:39:55 +08:00
Andreas Maechler
3db927e060 [jaxrs-spec] Add @Generated annotation to enums (#22829)
* Add @Generated annotation to enums in jaxrs-spec

- Adds @Generated annotation to enum classes

* Update all samples
2026-01-28 14:26:51 +08:00
Charaf Rezrazi
9fa18d0c81 feat(typescript): Update isomorphic-fetch file to allow for response streaming (#22673)
* Update isomorphic-fetch file to allow for response streaming (#1)

* Update samples/openapi3/client/petstore/typescript/builds/inversify/http/http.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update samples/client/echo_api/typescript/build/http/http.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update samples/openapi3/client/petstore/typescript/builds/object_params/http/http.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* update samples

* fix tests

---------

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-28 02:01:31 +08:00
Julian Vennen
6022e4ec7d [php][php-nextgen] Fix nullability when multiple response types are possible (#22827)
* [php][php-nextgen] Fix nullability when multiple response types are possible

* [php][php-nextgen] Fix test
2026-01-28 00:49:20 +08:00
William Cheng
11e06d1e77 update assertj to newer version (#22824) 2026-01-27 15:13:49 +08:00
William Cheng
3ed013966b [python-fastapi] Set python version to 3.10 (#22823)
* set python version to 3.10

* update doc
2026-01-27 14:15:25 +08:00
878 changed files with 13720 additions and 3630 deletions

View File

@@ -21,7 +21,7 @@ jobs:
- uses: actions/checkout@v5
- uses: actions/setup-python@v6
with:
python-version: '3.10'
python-version: '3.9'
- name: Test
working-directory: ${{ matrix.sample }}
run: make test-all

View File

@@ -64,6 +64,15 @@ jobs:
if cargo read-manifest | grep -q '"validate"'; then
cargo build --features validate --all-targets
fi
# Test TLS features if they exist
if cargo read-manifest | grep -q '"client-tls"'; then
# Client without TLS (HTTP-only)
cargo build --no-default-features --features=client --lib
# Client with TLS (using native-tls)
cargo build --no-default-features --features=client,client-tls --lib
# Server without TLS
cargo build --no-default-features --features=server --lib
fi
cargo fmt
cargo test
cargo clippy

View File

@@ -723,3 +723,10 @@ Into this securityScheme:
scheme: bearer
type: http
```
- `SORT_MODEL_PROPERTIES`: When set to true, model properties will be sorted alphabetically by name. This ensures deterministic code generation output regardless of property ordering in the source spec.
Example:
```
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -o /tmp/java-okhttp/ --openapi-normalizer SORT_MODEL_PROPERTIES=true
```

View File

@@ -30,6 +30,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|legacy|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -44,6 +44,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|configPackage|configuration package for generated code| |org.openapitools.configuration|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|java8|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|delegatePattern|Whether to generate the server files using the delegate pattern| |false|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
@@ -110,7 +111,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useOptional|Use Optional container for optional parameters| |false|
|useResponseEntity|Use the `ResponseEntity` type to wrap return values of generated API methods. If disabled, method are annotated using a `@ResponseStatus` annotation, which has the status of the first response declared in the Api definition| |true|
|useSealed|Whether to generate sealed model interfaces and classes| |false|
|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.| |false|
|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot &ge; 3 (use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.| |false|
|useSpringBuiltInValidation|Disable `@Validated` at the class level when using built-in validation.| |false|
|useSpringController|Annotate the generated API as a Spring Controller| |false|
|useSwaggerUI|Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies| |true|

View File

@@ -34,6 +34,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|configPackage|configuration package for generated code| |org.openapitools.configuration|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|java8|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -33,6 +33,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|configKey|Config key in @RegisterRestClient. Default to none.| |null|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|java8|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|disableDiscriminatorJsonIgnoreProperties|Ignore discriminator field type for Jackson serialization| |false|
|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.|<dl><dt>**false**</dt><dd>The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.</dd><dt>**true**</dt><dd>Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.</dd></dl>|true|
|discriminatorCaseSensitive|Whether the discriminator value lookup should be case-sensitive or not. This option only works for Java API client| |true|

View File

@@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|java8|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|disableDiscriminatorJsonIgnoreProperties|Ignore discriminator field type for Jackson serialization| |false|
|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.|<dl><dt>**false**</dt><dd>The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.</dd><dt>**true**</dt><dd>Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.</dd></dl>|true|
|discriminatorCaseSensitive|Whether the discriminator value lookup should be case-sensitive or not. This option only works for Java API client| |true|

View File

@@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|legacy|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -41,6 +41,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|dateFormat|Specify the format pattern of date as a string| |null|
|dateLibrary|Option. Date library to use|<dl><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|java8|
|datetimeFormat|Specify the format pattern of date-time as a string| |null|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -36,6 +36,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|dateFormat|Specify the format pattern of date as a string| |null|
|dateLibrary|Option. Date library to use|<dl><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|java8|
|datetimeFormat|Specify the format pattern of date-time as a string| |null|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -37,6 +37,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|configKeyFromClassName|If true, set tag as key in @RegisterRestClient. Default to false. Only `microprofile` supports this option.| |null|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|java8|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|legacy|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -33,6 +33,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|java8|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -35,6 +35,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|controllerOnly|Whether to generate only API interface stubs without the server files.| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|java8|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|legacy|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|java8|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|java8|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|java8|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -37,6 +37,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|configKeyFromClassName|If true, set tag as key in @RegisterRestClient. Default to false. Only `microprofile` supports this option.| |null|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|java8|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|legacy|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -33,6 +33,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|legacy|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -34,6 +34,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|legacy|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -34,6 +34,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|legacy|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|legacy|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|legacy|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|legacy|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|camelCaseDollarSign|Fix camelCase when starting with $ sign. when true : $Value when false : $value| |false|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|legacy|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
|developerOrganization|developer organization in generated pom.xml| |OpenAPITools.org|

View File

@@ -56,7 +56,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useFeignClientUrl|Whether to generate Feign client with url parameter.| |true|
|useFlowForArrayReturnType|Whether to use Flow for array/collection return types when reactive is enabled. If false, will use List instead.| |true|
|useResponseEntity|Whether (when false) to return actual type (e.g. List&lt;Fruit&gt;) and handle non-happy path responses via exceptions flow or (when true) return entire ResponseEntity (e.g. ResponseEntity&lt;List&lt;Fruit&gt;&gt;). If disabled, method are annotated using a @ResponseStatus annotation, which has the status of the first response declared in the Api definition| |true|
|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.| |false|
|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot &ge; 3 (use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.| |false|
|useSwaggerUI|Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies| |true|
|useTags|Whether to use tags for creating interface and controller class names| |false|

View File

@@ -22,6 +22,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|aggregateModelsName|Aggregated model filename. If set, all generated models will be combined into this single file.| |null|
|customOptionsApi|Custom options for the api files.| |null|
|customOptionsModel|Custom options for the model files.| |null|
|extractEnumsToSeparateFiles|Extract enums to separate protobuf files and import them in models| |false|
|numberedFieldNumberList|Field numbers in order.| |false|
|startEnumsWithUnspecified|Introduces &quot;UNSPECIFIED&quot; as the first element of enumerations.| |false|
|supportMultipleResponses|Support multiple responses| |true|

View File

@@ -10,7 +10,7 @@ title: Documentation for the python-fastapi Generator
| generator stability | BETA | |
| generator type | SERVER | |
| generator language | Python | |
| generator language version | 3.7 | |
| generator language version | 3.10 | |
| generator default templating engine | mustache | |
| helpTxt | Generates a Python FastAPI server (beta). Models are defined with the pydantic library | |

View File

@@ -37,6 +37,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|configPackage|configuration package for generated code| |org.openapitools.configuration|
|containerDefaultToNull|Set containers (array, set, map) default to null| |false|
|dateLibrary|Option. Date library to use|<dl><dt>**joda**</dt><dd>Joda (for legacy app only)</dd><dt>**legacy**</dt><dd>Legacy java.util.Date</dd><dt>**java8-localdatetime**</dt><dd>Java 8 using LocalDateTime (for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (preferred for jdk 1.8+)</dd></dl>|java8|
|defaultToEmptyContainer|Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values| |null|
|delegatePattern|Whether to generate the server files using the delegate pattern| |false|
|developerEmail|developer email in generated pom.xml| |team@openapitools.org|
|developerName|developer name in generated pom.xml| |OpenAPI-Generator Contributors|
@@ -103,7 +104,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useOptional|Use Optional container for optional parameters| |false|
|useResponseEntity|Use the `ResponseEntity` type to wrap return values of generated API methods. If disabled, method are annotated using a `@ResponseStatus` annotation, which has the status of the first response declared in the Api definition| |true|
|useSealed|Whether to generate sealed model interfaces and classes| |false|
|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.| |false|
|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot &ge; 3 (use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.| |false|
|useSpringBuiltInValidation|Disable `@Validated` at the class level when using built-in validation.| |false|
|useSpringController|Annotate the generated API as a Spring Controller| |false|
|useSwaggerUI|Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies| |true|

View File

@@ -162,8 +162,8 @@ This gives access to the following tasks:
| Task | Description |
|---------------------------|---------------------------------------------------------------------------------------------|
| <configName>.generate | Generate code via Open API Tools Generator for Open API 2.0 or 3.x specification documents. |
| <configName>.validateSpec | Validates the configured spec |
| &lt;configName&gt;.generate | Generate code via Open API Tools Generator for Open API 2.0 or 3.x specification documents. |
| &lt;configName&gt;.validateSpec | Validates the configured spec |
and a command

View File

@@ -456,6 +456,7 @@ public class CodegenConstants {
public static final String USE_DEFAULT_VALUES_FOR_REQUIRED_VARS = "useDefaultValuesForRequiredVars";
public static final String DEFAULT_TO_EMPTY_CONTAINER = "defaultToEmptyContainer";
public static final String DEFAULT_TO_EMPTY_CONTAINER_DESC = "Initialize containers (array/set/map) to empty containers instead of null by default. Usage: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md#default-values";
// Vendor extensions
public static final String X_INTERNAL = "x-internal";

View File

@@ -88,6 +88,10 @@ public class CodegenDiscriminator {
this.explicitMapping = explicitMapping;
}
public boolean isExplicitMapping() {
return explicitMapping;
}
public MappedModel(String mappingName, String modelName) {
this(mappingName, modelName, false);
}

View File

@@ -151,6 +151,9 @@ public class OpenAPINormalizer {
boolean updateNumberToNullable;
boolean updateBooleanToNullable;
// when set to true, sort model properties by name to ensure deterministic output
final String SORT_MODEL_PROPERTIES = "SORT_MODEL_PROPERTIES";
// ============= end of rules =============
/**
@@ -209,6 +212,7 @@ public class OpenAPINormalizer {
ruleNames.add(SET_PRIMITIVE_TYPES_TO_NULLABLE);
ruleNames.add(SIMPLIFY_ONEOF_ANYOF_ENUM);
ruleNames.add(REMOVE_PROPERTIES_FROM_TYPE_OTHER_THAN_OBJECT);
ruleNames.add(SORT_MODEL_PROPERTIES);
// rules that are default to true
rules.put(SIMPLIFY_ONEOF_ANYOF, true);
@@ -768,7 +772,7 @@ public class OpenAPINormalizer {
}
if (schema.getProperties() != null && !schema.getProperties().isEmpty()) {
normalizeProperties(schema.getProperties(), visitedSchemas);
normalizeProperties(schema, visitedSchemas);
}
if (schema.getAdditionalProperties() != null) {
@@ -777,7 +781,7 @@ public class OpenAPINormalizer {
return schema;
} else if (schema.getProperties() != null && !schema.getProperties().isEmpty()) {
normalizeProperties(schema.getProperties(), visitedSchemas);
normalizeProperties(schema, visitedSchemas);
} else if (schema.getAdditionalProperties() instanceof Schema) { // map
normalizeMapSchema(schema);
normalizeSchema((Schema) schema.getAdditionalProperties(), visitedSchemas);
@@ -880,10 +884,19 @@ public class OpenAPINormalizer {
processSetPrimitiveTypesToNullable(schema);
}
protected void normalizeProperties(Map<String, Schema> properties, Set<Schema> visitedSchemas) {
protected void normalizeProperties(Schema schema, Set<Schema> visitedSchemas) {
Map<String, Schema> properties = schema.getProperties();
if (properties == null) {
return;
}
// Sort properties by name if rule is enabled
if (getRule(SORT_MODEL_PROPERTIES)) {
Map<String, Schema> sortedProperties = new TreeMap<>(properties);
schema.setProperties(sortedProperties);
properties = sortedProperties;
}
for (Map.Entry<String, Schema> propertiesEntry : properties.entrySet()) {
Schema property = propertiesEntry.getValue();
@@ -1089,7 +1102,7 @@ public class OpenAPINormalizer {
protected Schema normalizeComplexComposedSchema(Schema schema, Set<Schema> visitedSchemas) {
// loop through properties, if any
if (schema.getProperties() != null && !schema.getProperties().isEmpty()) {
normalizeProperties(schema.getProperties(), visitedSchemas);
normalizeProperties(schema, visitedSchemas);
}
processRemoveAnyOfOneOfAndKeepPropertiesOnly(schema);

View File

@@ -378,6 +378,8 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
CliOption enumPropertyNamingOpt = new CliOption(CodegenConstants.ENUM_PROPERTY_NAMING, ENUM_PROPERTY_NAMING_DESC);
cliOptions.add(enumPropertyNamingOpt.defaultValue(enumPropertyNaming.name()));
cliOptions.add(CliOption.newString(CodegenConstants.DEFAULT_TO_EMPTY_CONTAINER, CodegenConstants.DEFAULT_TO_EMPTY_CONTAINER_DESC));
}
@Override

View File

@@ -608,7 +608,7 @@ public class GoClientCodegen extends AbstractGoCodegen {
} else if (codegenParameter.isPrimitiveType) { // primitive type
if (codegenParameter.isString) {
if (!StringUtils.isEmpty(codegenParameter.example) && !"null".equals(codegenParameter.example)) {
return "\"" + codegenParameter.example + "\"";
return "\"" + escapeText(codegenParameter.example) + "\"";
} else {
return "\"" + codegenParameter.paramName + "_example\"";
}
@@ -640,7 +640,7 @@ public class GoClientCodegen extends AbstractGoCodegen {
return constructExampleCode(modelMaps.get(codegenParameter.dataType), modelMaps, processedModelMap, 0);
} else if (codegenParameter.isEmail) { // email
if (!StringUtils.isEmpty(codegenParameter.example) && !"null".equals(codegenParameter.example)) {
return "\"" + codegenParameter.example + "\"";
return "\"" + escapeText(codegenParameter.example) + "\"";
} else {
return "\"" + codegenParameter.paramName + "@example.com\"";
}
@@ -681,7 +681,7 @@ public class GoClientCodegen extends AbstractGoCodegen {
} else if (codegenProperty.isPrimitiveType) { // primitive type
if (codegenProperty.isString) {
if (!StringUtils.isEmpty(codegenProperty.example) && !"null".equals(codegenProperty.example)) {
return "\"" + codegenProperty.example + "\"";
return "\"" + escapeText(codegenProperty.example) + "\"";
} else {
return "\"" + codegenProperty.name + "_example\"";
}
@@ -714,7 +714,7 @@ public class GoClientCodegen extends AbstractGoCodegen {
return constructExampleCode(modelMaps.get(codegenProperty.dataType), modelMaps, processedModelMap, depth + 1);
} else if (codegenProperty.isEmail) { // email
if (!StringUtils.isEmpty(codegenProperty.example) && !"null".equals(codegenProperty.example)) {
return "\"" + codegenProperty.example + "\"";
return "\"" + escapeText(codegenProperty.example) + "\"";
} else {
return "\"" + codegenProperty.name + "@example.com\"";
}

View File

@@ -241,7 +241,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
addSwitch(BEAN_QUALIFIERS, "Whether to add fully-qualifier class names as bean qualifiers in @Component and " +
"@RestController annotations. May be used to prevent bean names clash if multiple generated libraries" +
" (contexts) added to single project.", beanQualifiers);
addSwitch(USE_SPRING_BOOT3, "Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.", useSpringBoot3);
addSwitch(USE_SPRING_BOOT3, "Generate code and provide dependencies for use with Spring Boot ≥ 3 (use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.", useSpringBoot3);
addSwitch(USE_FLOW_FOR_ARRAY_RETURN_TYPE, "Whether to use Flow for array/collection return types when reactive is enabled. If false, will use List instead.", useFlowForArrayReturnType);
addSwitch(INCLUDE_HTTP_REQUEST_CONTEXT, "Whether to include HttpServletRequest (blocking) or ServerWebExchange (reactive) as additional parameter in generated methods.", includeHttpRequestContext);
addSwitch(USE_RESPONSE_ENTITY,

View File

@@ -214,7 +214,11 @@ public class PhpNextgenClientCodegen extends AbstractPhpCodegen {
String phpReturnType = String.join("|", phpReturnTypeOptions);
String docReturnType = String.join("|", docReturnTypeOptions);
if (hasEmptyResponse) {
phpReturnType = "?" + phpReturnType;
if (phpReturnTypeOptions.size() > 1) {
phpReturnType = phpReturnType + "|null";
} else {
phpReturnType = "?" + phpReturnType;
}
docReturnType = docReturnType + "|null";
}

View File

@@ -330,7 +330,7 @@ public class PythonFastAPIServerCodegen extends AbstractPythonCodegen {
@Override
public String generatorLanguageVersion() {
return "3.7";
return "3.10";
}
@Override

View File

@@ -601,6 +601,7 @@ public class RClientCodegen extends DefaultCodegen implements CodegenConfig {
public ModelsMap postProcessModels(ModelsMap objs) {
for (ModelMap mo : objs.getModels()) {
CodegenModel cm = mo.getModel();
boolean needsExtractSimpleType = false;
for (CodegenProperty var : cm.vars) {
// check to see if base name is an empty string
if ("".equals(var.baseName)) {
@@ -608,10 +609,17 @@ public class RClientCodegen extends DefaultCodegen implements CodegenConfig {
var.baseName = "empty_string";
}
if (!var.isPrimitiveType) {
needsExtractSimpleType = true;
}
// create extension x-r-doc-type to store the data type in r doc format
var.vendorExtensions.put("x-r-doc-type", constructRdocType(var));
}
// create extension x-r-has-non-primitive-field to indicate whether generated models need special handling for complex types
cm.vendorExtensions.put("x-r-has-non-primitive-field", needsExtractSimpleType);
// apply the same fix, enhancement for allVars
for (CodegenProperty var : cm.allVars) {
// check to see if base name is an empty string

View File

@@ -610,6 +610,10 @@ public class RustServerCodegen extends AbstractRustCodegen implements CodegenCon
processParam(param, op);
}
for (CodegenParameter param : op.pathParams) {
processParam(param, op);
}
// We keep track of the 'default' model type for this API. If there are
// *any* XML responses, then we set the default to XML, otherwise we
// let the default be JSON. It would be odd for an API to want to use
@@ -1459,6 +1463,45 @@ public class RustServerCodegen extends AbstractRustCodegen implements CodegenCon
return null;
}
/**
* Determine the appropriate Rust integer type based on format and min/max constraints.
* Returns the fitted data type, or null if the baseType is not an integer.
*
* @param dataFormat The data format (e.g., "int32", "int64", "uint32", "uint64")
* @param minimum The minimum value constraint
* @param maximum The maximum value constraint
* @param exclusiveMinimum Whether the minimum is exclusive
* @param exclusiveMaximum Whether the maximum is exclusive
* @return The fitted Rust integer type.
*/
private String applyIntegerTypeFitting(String dataFormat,
String minimum, String maximum,
boolean exclusiveMinimum, boolean exclusiveMaximum) {
BigInteger min = Optional.ofNullable(minimum).filter(s -> !s.isEmpty()).map(BigInteger::new).orElse(null);
BigInteger max = Optional.ofNullable(maximum).filter(s -> !s.isEmpty()).map(BigInteger::new).orElse(null);
boolean unsigned = canFitIntoUnsigned(min, exclusiveMinimum);
if (Strings.isNullOrEmpty(dataFormat)) {
return bestFittingIntegerType(min, exclusiveMinimum, max, exclusiveMaximum, true);
} else {
switch (dataFormat) {
// custom integer formats (legacy)
case "uint32":
return "u32";
case "uint64":
return "u64";
case "int32":
return unsigned ? "u32" : "i32";
case "int64":
return unsigned ? "u64" : "i64";
default:
LOGGER.warn("The integer format '{}' is not recognized and will be ignored.", dataFormat);
return bestFittingIntegerType(min, exclusiveMinimum, max, exclusiveMaximum, true);
}
}
}
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
super.postProcessModelProperty(model, property);
@@ -1492,41 +1535,12 @@ public class RustServerCodegen extends AbstractRustCodegen implements CodegenCon
// Integer type fitting
if (Objects.equals(property.baseType, "integer")) {
BigInteger minimum = Optional.ofNullable(property.getMinimum()).map(BigInteger::new).orElse(null);
BigInteger maximum = Optional.ofNullable(property.getMaximum()).map(BigInteger::new).orElse(null);
boolean unsigned = canFitIntoUnsigned(minimum, property.getExclusiveMinimum());
if (Strings.isNullOrEmpty(property.dataFormat)) {
property.dataType = bestFittingIntegerType(minimum,
property.getExclusiveMinimum(),
maximum,
property.getExclusiveMaximum(),
true);
} else {
switch (property.dataFormat) {
// custom integer formats (legacy)
case "uint32":
property.dataType = "u32";
break;
case "uint64":
property.dataType = "u64";
break;
case "int32":
property.dataType = unsigned ? "u32" : "i32";
break;
case "int64":
property.dataType = unsigned ? "u64" : "i64";
break;
default:
LOGGER.warn("The integer format '{}' is not recognized and will be ignored.", property.dataFormat);
property.dataType = bestFittingIntegerType(minimum,
property.getExclusiveMinimum(),
maximum,
property.getExclusiveMaximum(),
true);
}
}
property.dataType = applyIntegerTypeFitting(
property.dataFormat,
property.getMinimum(),
property.getMaximum(),
property.getExclusiveMinimum(),
property.getExclusiveMaximum());
}
property.name = underscore(property.name);
@@ -1580,6 +1594,17 @@ public class RustServerCodegen extends AbstractRustCodegen implements CodegenCon
private void processParam(CodegenParameter param, CodegenOperation op) {
String example = null;
// If a parameter is an integer, fit it into the right type.
// Note: For CodegenParameter, baseType may be null, so we check isInteger/isLong/isShort flags instead.
if (param.isInteger || param.isLong || param.isShort) {
param.dataType = applyIntegerTypeFitting(
param.dataFormat,
param.minimum,
param.maximum,
param.exclusiveMinimum,
param.exclusiveMaximum);
}
// If a parameter uses UUIDs, we need to import the UUID package.
if (uuidType.equals(param.dataType)) {
additionalProperties.put("apiUsesUuid", true);

View File

@@ -276,7 +276,7 @@ public class SpringCodegen extends AbstractJavaCodegen
"Use `equalsIgnoreCase` when String for enum comparison",
useEnumCaseInsensitive));
cliOptions.add(CliOption.newBoolean(USE_SPRING_BOOT3,
"Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.",
"Generate code and provide dependencies for use with Spring Boot ≥ 3 (use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.",
useSpringBoot3));
cliOptions.add(CliOption.newBoolean(GENERATE_CONSTRUCTOR_WITH_REQUIRED_ARGS,
"Whether to generate constructors with required args for models",

View File

@@ -0,0 +1,34 @@
{{#jackson}}
{{#additionalPropertiesType}}
/**
* Set the additional (undeclared) property with the specified name and value.
* Creates the property if it does not already exist, otherwise replaces it.
* @param key the name of the property
* @param value the value of the property
* @return self reference
*/
@JsonAnySetter
public {{classname}} putAdditionalProperty(String key, {{{.}}} value) {
this.put(key, value);
return this;
}
/**
* Return the additional (undeclared) properties.
* @return the additional (undeclared) properties
*/
@JsonAnyGetter
public Map<String, {{{.}}}> getAdditionalProperties() {
return this;
}
/**
* Return the additional (undeclared) property with the specified name.
* @param key the name of the property
* @return the additional (undeclared) property with the specified name
*/
public {{{.}}} getAdditionalProperty(String key) {
return this.get(key);
}
{{/additionalPropertiesType}}
{{/jackson}}

View File

@@ -311,7 +311,7 @@
{{/useJakartaEe}}
<threetenbp-version>2.9.10</threetenbp-version>
<maven-plugin-version>1.0.0</maven-plugin-version>
<assertj-version>3.23.1</assertj-version>
<assertj-version>3.27.7</assertj-version>
<junit-version>5.10.2</junit-version>
</properties>
</project>

View File

@@ -784,9 +784,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
break;
} catch (HttpServerErrorException | HttpClientErrorException ex) {
if (ex instanceof HttpServerErrorException
|| ((HttpClientErrorException) ex)
.getStatusCode()
.equals(HttpStatus.TOO_MANY_REQUESTS)) {
|| ex.getStatusCode().equals(HttpStatus.TOO_MANY_REQUESTS)) {
attempts++;
if (attempts < maxAttemptsForRetry) {
try {

View File

@@ -17,6 +17,17 @@ import java.io.Serializable;
{{#jackson}}
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.annotation.JsonTypeName;
{{#models}}
{{#model}}
{{#additionalPropertiesType}}
import java.util.Map;
import java.util.HashMap;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonFormat;
{{/additionalPropertiesType}}
{{/model}}
{{/models}}
{{#withXml}}
import com.fasterxml.jackson.dataformat.xml.annotation.*;
{{/withXml}}

View File

@@ -24,6 +24,9 @@
@JsonTypeName("{{name}}")
{{/hasDiscriminatorWithNonEmptyMapping}}
{{/isClassnameSanitized}}
{{#additionalPropertiesType}}
@JsonFormat(shape=JsonFormat.Shape.OBJECT)
{{/additionalPropertiesType}}
{{/jackson}}
{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}}
{{#vendorExtensions.x-class-extra-annotation}}
@@ -281,6 +284,8 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
{{/isReadOnly}}
{{/vars}}
{{>additional_properties}}
{{#parent}}
{{#readWriteVars}}
{{#isOverridden}}

View File

@@ -0,0 +1,32 @@
{{#additionalProperties}}
/**
* Set the additional (undeclared) property with the specified name and value.
* Creates the property if it does not already exist, otherwise replaces it.
* @param key the name of the property
* @param value the value of the property
* @return self reference
*/
@JsonAnySetter
public {{classname}} putAdditionalProperty(String key, {{{datatypeWithEnum}}} value) {
this.put(key, value);
return this;
}
/**
* Return the additional (undeclared) properties.
* @return the additional (undeclared) properties
*/
@JsonAnyGetter
public Map<String, {{{datatypeWithEnum}}}> getAdditionalProperties() {
return this;
}
/**
* Return the additional (undeclared) property with the specified name.
* @param key the name of the property
* @return the additional (undeclared) property with the specified name
*/
public {{{datatypeWithEnum}}} getAdditionalProperty(String key) {
return this.get(key);
}
{{/additionalProperties}}

View File

@@ -6,6 +6,8 @@ import com.fasterxml.jackson.annotation.JsonValue;
/**
* {{description}}{{^description}}Gets or Sets {{{name}}}{{/description}}
*/
{{>generatedAnnotation}}
{{>additionalEnumTypeAnnotations}}public enum {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} {
{{#gson}}
{{#allowableValues}}{{#enumVars}}

View File

@@ -10,6 +10,13 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.annotation.JsonTypeName;
{{#additionalProperties}}
import java.util.Map;
import java.util.HashMap;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonFormat;
{{/additionalProperties}}
{{/jackson}}
{{#openApiNullable}}
import org.openapitools.jackson.nullable.JsonNullable;
@@ -30,7 +37,12 @@ import {{javaxPackage}}.xml.bind.annotation.XmlEnumValue;
{{#useSwaggerAnnotations}}{{#description}}@ApiModel(description = "{{{.}}}"){{/description}}{{/useSwaggerAnnotations}}{{#useSwaggerV3Annotations}}
@Schema({{#title}}title="{{{.}}}", {{/title}}{{#description}}description="{{{.}}}"{{/description}}{{^description}}description=""{{/description}}){{/useSwaggerV3Annotations}}{{#useMicroProfileOpenAPIAnnotations}}
@org.eclipse.microprofile.openapi.annotations.media.Schema({{#title}}title="{{{.}}}", {{/title}}{{#description}}description="{{{.}}}"{{/description}}{{^description}}description=""{{/description}}){{/useMicroProfileOpenAPIAnnotations}}
{{#jackson}}@JsonTypeName("{{name}}"){{/jackson}}
{{#jackson}}
@JsonTypeName("{{name}}")
{{#additionalProperties}}
@JsonFormat(shape=JsonFormat.Shape.OBJECT)
{{/additionalProperties}}
{{/jackson}}
{{>generatedAnnotation}}{{>additionalModelTypeAnnotations}}{{>xmlPojoAnnotation}}
{{#vendorExtensions.x-class-extra-annotation}}
{{{vendorExtensions.x-class-extra-annotation}}}
@@ -196,6 +208,7 @@ public class {{classname}} {{#parent}}extends {{{.}}}{{/parent}} {{#vendorExtens
}
{{/isMap}}
{{/vars}}
{{>additional_properties}}
@Override
public boolean equals(Object o) {

View File

@@ -176,7 +176,7 @@ import {{packageName}}.infrastructure.ITransformForStorage
override fun deserialize(decoder: Decoder): {{nameInPascalCase}} {
val value = decoder.decodeSerializableValue({{^isContainer}}{{dataType}}{{/isContainer}}{{#isContainer}}kotlin.String{{/isContainer}}.serializer())
return {{nameInPascalCase}}.values().firstOrNull { it.value == value }
return {{nameInPascalCase}}.entries.firstOrNull { it.value == value }
?: {{nameInPascalCase}}.{{#allowableValues}}{{#enumVars}}{{#-last}}{{&name}}{{/-last}}{{/enumVars}}{{/allowableValues}}
}
@@ -360,14 +360,14 @@ import {{packageName}}.infrastructure.ITransformForStorage
{{#isEnum}}
{{#required}}
// validate the required field `{{{baseName}}}`
require({{{datatypeWithEnum}}}.values().any { it.value == jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].asString }) {
require({{{datatypeWithEnum}}}.entries.any { it.value == jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].asString }) {
String.format("Expected the field `{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}` to be valid `{{{datatypeWithEnum}}}` enum value in the JSON string but got `%s`", jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].toString())
}
{{/required}}
{{^required}}
// validate the optional field `{{{baseName}}}`
if (jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"] != null && !jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].isJsonNull) {
require({{{datatypeWithEnum}}}.values().any { it.value == jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].asString }) {
require({{{datatypeWithEnum}}}.entries.any { it.value == jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].asString }) {
String.format("Expected the field `{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}` to be valid `{{{datatypeWithEnum}}}` enum value in the JSON string but got `%s`", jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].toString())
}
}
@@ -376,14 +376,14 @@ import {{packageName}}.infrastructure.ITransformForStorage
{{#isEnumRef}}
{{#required}}
// validate the required field `{{{baseName}}}`
require({{{dataType}}}.values().any { it.value == jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].asString }) {
require({{{dataType}}}.entries.any { it.value == jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].asString }) {
String.format("Expected the field `{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}` to be valid `{{{dataType}}}` enum value in the JSON string but got `%s`", jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].toString())
}
{{/required}}
{{^required}}
// validate the optional field `{{{baseName}}}`
if (jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"] != null && !jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].isJsonNull) {
require({{{dataType}}}.values().any { it.value == jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].asString }) {
require({{{dataType}}}.entries.any { it.value == jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].asString }) {
String.format("Expected the field `{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}` to be valid `{{{dataType}}}` enum value in the JSON string but got `%s`", jsonObj["{{#lambda.escapeDollar}}{{baseName}}{{/lambda.escapeDollar}}"].toString())
}
}

View File

@@ -21,4 +21,4 @@
{{#deprecated}}
@Deprecated(message = "This property is deprecated.")
{{/deprecated}}
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") {{/multiplatform}}{{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isArray}}{{#isList}}{{#uniqueItems}}kotlin.collections.{{#modelMutable}}Mutable{{/modelMutable}}Set{{/uniqueItems}}{{^uniqueItems}}kotlin.collections.{{#modelMutable}}Mutable{{/modelMutable}}List{{/uniqueItems}}{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{^items.isEnum}}{{^items.isPrimitiveType}}{{^items.isModel}}{{#kotlinx_serialization}}@Contextual {{/kotlinx_serialization}}{{/items.isModel}}{{/items.isPrimitiveType}}{{{items.dataType}}}{{/items.isEnum}}{{#items.isEnum}}{{classname}}.{{{nameInPascalCase}}}{{/items.isEnum}}>{{/isArray}}{{^isEnum}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{classname}}.{{{nameInPascalCase}}}{{/isArray}}{{/isEnum}}? = {{^defaultValue}}null{{/defaultValue}}{{#defaultValue}}{{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{^multiplatform}}{{{dataType}}}("{{{defaultValue}}}"){{/multiplatform}}{{#multiplatform}}({{{defaultValue}}}).toDouble(){{/multiplatform}}{{/isNumber}}{{/defaultValue}}
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") {{/multiplatform}}{{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isArray}}{{#isList}}kotlin.collections.{{#modelMutable}}Mutable{{/modelMutable}}{{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{^items.isEnum}}{{^items.isPrimitiveType}}{{^items.isModel}}{{#kotlinx_serialization}}@Contextual {{/kotlinx_serialization}}{{/items.isModel}}{{/items.isPrimitiveType}}{{{items.dataType}}}{{/items.isEnum}}{{#items.isEnum}}{{classname}}.{{{nameInPascalCase}}}{{/items.isEnum}}>{{/isArray}}{{^isEnum}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{classname}}.{{{nameInPascalCase}}}{{/isArray}}{{/isEnum}}? = {{^defaultValue}}null{{/defaultValue}}{{#defaultValue}}{{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{^multiplatform}}{{{dataType}}}("{{{defaultValue}}}"){{/multiplatform}}{{#multiplatform}}({{{defaultValue}}}).toDouble(){{/multiplatform}}{{/isNumber}}{{/defaultValue}}

View File

@@ -21,4 +21,4 @@
{{#deprecated}}
@Deprecated(message = "This property is deprecated.")
{{/deprecated}}
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") @Required {{/multiplatform}}{{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isArray}}{{#isList}}{{#uniqueItems}}kotlin.collections.{{#modelMutable}}Mutable{{/modelMutable}}Set{{/uniqueItems}}{{^uniqueItems}}kotlin.collections.{{#modelMutable}}Mutable{{/modelMutable}}List{{/uniqueItems}}{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{^items.isEnum}}{{^items.isPrimitiveType}}{{^items.isModel}}{{#kotlinx_serialization}}@Contextual {{/kotlinx_serialization}}{{/items.isModel}}{{/items.isPrimitiveType}}{{{items.dataType}}}{{/items.isEnum}}{{#items.isEnum}}{{classname}}.{{{nameInPascalCase}}}{{/items.isEnum}}>{{/isArray}}{{^isEnum}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{classname}}.{{{nameInPascalCase}}}{{/isArray}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{^multiplatform}}{{{dataType}}}("{{{defaultValue}}}"){{/multiplatform}}{{#multiplatform}}({{{defaultValue}}}).toDouble(){{/multiplatform}}{{/isNumber}}{{/defaultValue}}
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") @Required {{/multiplatform}}{{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isArray}}{{#isList}}kotlin.collections.{{#modelMutable}}Mutable{{/modelMutable}}{{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{^items.isEnum}}{{^items.isPrimitiveType}}{{^items.isModel}}{{#kotlinx_serialization}}@Contextual {{/kotlinx_serialization}}{{/items.isModel}}{{/items.isPrimitiveType}}{{{items.dataType}}}{{/items.isEnum}}{{#items.isEnum}}{{classname}}.{{{nameInPascalCase}}}{{/items.isEnum}}>{{/isArray}}{{^isEnum}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{classname}}.{{{nameInPascalCase}}}{{/isArray}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}{{^multiplatform}}{{{dataType}}}("{{{defaultValue}}}"){{/multiplatform}}{{#multiplatform}}({{{defaultValue}}}).toDouble(){{/multiplatform}}{{/isNumber}}{{/defaultValue}}

View File

@@ -109,7 +109,7 @@ import kotlinx.serialization.*
{{^jackson}}
{{^nonPublicApi}}{{#explicitApi}}public {{/explicitApi}}{{/nonPublicApi}}fun decode(data: kotlin.Any?): {{classname}}? = data?.let {
val normalizedData = "$it".lowercase()
values().firstOrNull { value ->
entries.firstOrNull { value ->
it == value || normalizedData == "$value".lowercase()
}
}
@@ -127,7 +127,7 @@ import kotlinx.serialization.*
{{/isNullable}}
}
val normalizedData = "$data".lowercase()
return values().firstOrNull { value ->
return entries.firstOrNull { value ->
data == value || normalizedData == "$value".lowercase()
}{{#isNullable}}{{/isNullable}}{{^isNullable}}{{#enumUnknownDefaultCase}}
?: {{#allowableValues}}{{#enumVars}}{{#-last}}{{&name}}{{/-last}}{{/enumVars}}{{/allowableValues}}{{/enumUnknownDefaultCase}}{{^enumUnknownDefaultCase}}
@@ -142,7 +142,7 @@ internal object {{classname}}Serializer : KSerializer<{{classname}}> {
override fun deserialize(decoder: Decoder): {{classname}} {
val value = decoder.decodeSerializableValue({{{dataType}}}.serializer())
return {{classname}}.values().firstOrNull { it.value == value }
return {{classname}}.entries.firstOrNull { it.value == value }
{{#isString}}
?: {{classname}}.{{#allowableValues}}{{#enumVars}}{{#-last}}{{&name}}{{/-last}}{{/enumVars}}{{/allowableValues}}
{{/isString}}
@@ -162,7 +162,7 @@ internal object {{classname}}Serializer : KSerializer<{{classname}}> {
override fun deserialize(decoder: Decoder): {{classname}} {
val value = decoder.decodeSerializableValue({{{dataType}}}.serializer())
return {{classname}}.values().firstOrNull { it.value == value }
return {{classname}}.entries.firstOrNull { it.value == value }
?: throw IllegalArgumentException("Unknown enum value: $value")
}

View File

@@ -15,4 +15,4 @@
{{^isEnum}}{{^isArray}}{{^isPrimitiveType}}{{^isModel}}@Contextual {{/isModel}}{{/isPrimitiveType}}{{/isArray}}{{/isEnum}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}")
{{/kotlinx_serialization}}
{{/multiplatform}}
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") abstract {{/multiplatform}}{{#kotlinx_serialization}}abstract {{/kotlinx_serialization}}{{>modelMutable}} {{{name}}}: {{#isArray}}{{#isList}}kotlin.collections.{{#modelMutable}}Mutable{{/modelMutable}}List{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{^items.isEnum}}{{^items.isPrimitiveType}}{{^items.isModel}}{{#kotlinx_serialization}}@Contextual {{/kotlinx_serialization}}{{/items.isModel}}{{/items.isPrimitiveType}}{{{items.dataType}}}{{/items.isEnum}}{{#items.isEnum}}{{classname}}.{{{nameInPascalCase}}}{{/items.isEnum}}>{{/isArray}}{{^isEnum}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{classname}}.{{{nameInPascalCase}}}{{/isArray}}{{/isEnum}}?
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") abstract {{/multiplatform}}{{#kotlinx_serialization}}abstract {{/kotlinx_serialization}}{{>modelMutable}} {{{name}}}: {{#isArray}}{{#isList}}kotlin.collections.{{#modelMutable}}Mutable{{/modelMutable}}{{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{^items.isEnum}}{{^items.isPrimitiveType}}{{^items.isModel}}{{#kotlinx_serialization}}@Contextual {{/kotlinx_serialization}}{{/items.isModel}}{{/items.isPrimitiveType}}{{{items.dataType}}}{{/items.isEnum}}{{#items.isEnum}}{{classname}}.{{{nameInPascalCase}}}{{/items.isEnum}}>{{/isArray}}{{^isEnum}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{classname}}.{{{nameInPascalCase}}}{{/isArray}}{{/isEnum}}?

View File

@@ -15,4 +15,4 @@
{{^isEnum}}{{^isArray}}{{^isPrimitiveType}}{{^isModel}}@Contextual {{/isModel}}{{/isPrimitiveType}}{{/isArray}}{{/isEnum}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}")
{{/kotlinx_serialization}}
{{/multiplatform}}
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") @Required abstract {{/multiplatform}}{{#kotlinx_serialization}}abstract {{/kotlinx_serialization}}{{>modelMutable}} {{{name}}}: {{#isArray}}{{#isList}}kotlin.collections.{{#modelMutable}}Mutable{{/modelMutable}}List{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{^items.isEnum}}{{^items.isPrimitiveType}}{{^items.isModel}}{{#kotlinx_serialization}}@Contextual {{/kotlinx_serialization}}{{/items.isModel}}{{/items.isPrimitiveType}}{{{items.dataType}}}{{/items.isEnum}}{{#items.isEnum}}{{classname}}.{{{nameInPascalCase}}}{{/items.isEnum}}>{{/isArray}}{{^isEnum}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{classname}}.{{{nameInPascalCase}}}{{/isArray}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}
{{#multiplatform}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") @Required abstract {{/multiplatform}}{{#kotlinx_serialization}}abstract {{/kotlinx_serialization}}{{>modelMutable}} {{{name}}}: {{#isArray}}{{#isList}}kotlin.collections.{{#modelMutable}}Mutable{{/modelMutable}}{{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{^items.isEnum}}{{^items.isPrimitiveType}}{{^items.isModel}}{{#kotlinx_serialization}}@Contextual {{/kotlinx_serialization}}{{/items.isModel}}{{/items.isPrimitiveType}}{{{items.dataType}}}{{/items.isEnum}}{{#items.isEnum}}{{classname}}.{{{nameInPascalCase}}}{{/items.isEnum}}>{{/isArray}}{{^isEnum}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{classname}}.{{{nameInPascalCase}}}{{/isArray}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}

View File

@@ -1,7 +1,26 @@
enum {{classname}} {
{{#allowableValues}}
{{#enumVars}}
{{{name}}} = {{{protobuf-enum-index}}};
{{/enumVars}}
{{/allowableValues}}
{{!
Generates an extracted enum wrapped in a message container.
This wrapper pattern is used to prevent enum value name collisions
in the Protocol Buffers global enum namespace. Multiple enums can
have values with the same name when wrapped in separate messages.
Generated format:
message EnumName {
enum Enum {
VALUE1 = 0;
VALUE2 = 1;
}
}
Usage in models: EnumName.Enum field_name = 1;
}}
message {{classname}} {
enum Enum {
{{#allowableValues}}
{{#enumVars}}
{{{name}}} = {{{protobuf-enum-index}}};
{{/enumVars}}
{{/allowableValues}}
}
}

View File

@@ -37,6 +37,7 @@ import public "{{{.}}}.proto";
{{#vendorExtensions.x-protobuf-type}}{{{.}}} {{/vendorExtensions.x-protobuf-type}}{{{vendorExtensions.x-protobuf-data-type}}} {{{name}}} = {{vendorExtensions.x-protobuf-index}}{{#vendorExtensions.x-protobuf-packed}} [packed=true]{{/vendorExtensions.x-protobuf-packed}}{{#vendorExtensions.x-protobuf-json-name}} [json_name="{{vendorExtensions.x-protobuf-json-name}}"]{{/vendorExtensions.x-protobuf-json-name}};
{{/isEnum}}
{{#isEnum}}
{{^vendorExtensions.x-protobuf-enum-reference-import}}
enum {{enumName}} {
{{#allowableValues}}
{{#enumVars}}
@@ -45,7 +46,8 @@ import public "{{{.}}}.proto";
{{/allowableValues}}
}
{{enumName}} {{name}} = {{vendorExtensions.x-protobuf-index}};
{{/vendorExtensions.x-protobuf-enum-reference-import}}
{{#vendorExtensions.x-protobuf-type}}{{{.}}} {{/vendorExtensions.x-protobuf-type}}{{{vendorExtensions.x-protobuf-data-type}}} {{name}} = {{vendorExtensions.x-protobuf-index}};
{{/isEnum}}
{{/vars}}

View File

@@ -242,7 +242,7 @@
self$`{{name}}`
{{/isPrimitiveType}}
{{^isPrimitiveType}}
lapply(self$`{{name}}`, function(x) x$toSimpleType())
self$extractSimpleType(self$`{{name}}`)
{{/isPrimitiveType}}
{{/isArray}}
{{#isMap}}
@@ -250,7 +250,7 @@
self$`{{name}}`
{{/isPrimitiveType}}
{{^isPrimitiveType}}
lapply(self$`{{name}}`, function(x) x$toSimpleType())
self$extractSimpleType(self$`{{name}}`)
{{/isPrimitiveType}}
{{/isMap}}
{{/isContainer}}
@@ -259,7 +259,7 @@
self$`{{name}}`
{{/isPrimitiveType}}
{{^isPrimitiveType}}
self$`{{name}}`$toSimpleType()
self$extractSimpleType(self$`{{name}}`)
{{/isPrimitiveType}}
{{/isContainer}}
}
@@ -272,6 +272,31 @@
{{/isAdditionalPropertiesTrue}}
return({{classname}}Object)
},
{{#vendorExtensions.x-r-has-non-primitive-field}}
extractSimpleType = function(x) {
if (R6::is.R6(x)) {
return(x$toSimpleType())
} else if (!self$hasNestedR6(x)) {
return(x)
}
lapply(x, self$extractSimpleType)
},
hasNestedR6 = function(x) {
if (R6::is.R6(x)) {
return(TRUE)
}
if (is.list(x)) {
for (item in x) {
if (self$hasNestedR6(item)) {
return(TRUE)
}
}
}
FALSE
},
{{/vendorExtensions.x-r-has-non-primitive-field}}
#' @description
#' Deserialize JSON string into an instance of {{{classname}}}

View File

@@ -32,7 +32,7 @@ homepage = "{{.}}"
{{/homePageUrl}}
[features]
default = ["client", "server"]
default = ["client", "server", "client-tls"]
client = [
{{#apiUsesMultipartFormData}}
"multipart", "multipart/client", "swagger/multipart_form",
@@ -47,7 +47,19 @@ client = [
"serde_ignored", "percent-encoding", {{^apiUsesByteArray}}"lazy_static", "regex",{{/apiUsesByteArray}}
{{/hasCallbacks}}
{{! Anything added to the list below, should probably be added to the callbacks list below }}
"hyper", "percent-encoding", "hyper-util/http1", "hyper-util/http2", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url"
"hyper", "percent-encoding", "hyper-util/http1", "hyper-util/http2", "url"
]
# TLS support - automatically selects backend based on target OS:
# - macOS/Windows/iOS: native-tls via hyper-tls
# - Other platforms: OpenSSL via hyper-openssl
# Dependencies are in target-specific sections below
client-tls = [
"client",
"dep:native-tls",
"dep:hyper-tls",
"dep:openssl",
"dep:hyper-openssl",
"swagger/tls"
]
server = [
{{#apiUsesMultipartFormData}}
@@ -57,7 +69,7 @@ server = [
"mime_multipart", "swagger/multipart_related",
{{/apiUsesMultipartRelated}}
{{#hasCallbacks}}
"native-tls", "hyper-openssl", "hyper-tls", "openssl",
"hyper-util/http1", "hyper-util/http2",
{{/hasCallbacks}}
{{! Anything added to the list below, should probably be added to the callbacks list above }}
"serde_ignored", "hyper", "percent-encoding", "url",
@@ -74,20 +86,12 @@ conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-
mock = ["mockall"]
validate = [{{^apiUsesByteArray}}"regex",{{/apiUsesByteArray}} "serde_valid", "swagger/serdevalid"]
[target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies]
native-tls = { version = "0.2", optional = true }
hyper-tls = { version = "0.6", optional = true }
[target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies]
hyper-openssl = { version = "0.10", optional = true }
openssl = { version = "0.10", optional = true }
[dependencies]
# Common
async-trait = "0.1.88"
chrono = { version = "0.4", features = ["serde"] }
futures = "0.3"
swagger = { version = "7.0.0", features = ["serdejson", "server", "client", "tls"] }
swagger = { version = "7.0.0", features = ["serdejson", "server", "client"] }
headers = "0.4.0"
log = "0.4.27"
@@ -157,6 +161,17 @@ frunk_core = { version = "0.4.3", optional = true }
frunk-enum-derive = { version = "0.3.0", optional = true }
frunk-enum-core = { version = "0.3.0", optional = true }
# TLS dependencies - platform-specific backends
# On macOS/Windows/iOS, use native-tls via hyper-tls
[target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies]
native-tls = { version = "0.2", optional = true }
hyper-tls = { version = "0.6", optional = true }
# On other platforms (Linux, etc.), use OpenSSL via hyper-openssl
[target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies]
openssl = { version = "0.10", optional = true }
hyper-openssl = { version = "0.10", optional = true }
[dev-dependencies]
always_send = "0.1.1"
clap = "4.5"
@@ -169,8 +184,8 @@ pin-project = "1.1.10"
jsonwebtoken = {version = "10.0.0", features = ["rust_crypto"]}
[target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies]
tokio-openssl = "0.6"
openssl = "0.10"
tokio-openssl = "0.6"
[[example]]
name = "client"

View File

@@ -126,6 +126,10 @@ The generated library has a few optional features that can be activated through
* `client`
* This defaults to enabled and creates the basic skeleton of a client implementation based on hyper
* The constructed client implements the API trait by making remote API call.
* `client-tls`
* This default to enabled and provides HTTPS support with automatic TLS backend selection:
- macOS/Windows/iOS: native-tls + hyper-tls
- Linux/Unix/others: OpenSSL + hyper-openssl
* `conversions`
* This defaults to disabled and creates extra derives on models to allow "transmogrification" between objects of structurally similar types.
* `cli`
@@ -134,6 +138,25 @@ The generated library has a few optional features that can be activated through
* This defaults to disabled and allows JSON Schema validation of received data using `MakeService::set_validation` or `Service::set_validation`.
* Note, enabling validation will have a performance penalty, especially if the API heavily uses regex based checks.
### HTTPS/TLS Support
HTTPS support is included by default. To disable it (for example, to reduce dependencies), you can:
```toml
[dependencies]
{{{packageName}}} = { version = "{{{packageVersion}}}", default-features = false, features = ["client", "server"] }
```
**For server with callbacks that need HTTPS:**
```toml
[dependencies]
{{{packageName}}} = { version = "{{{packageVersion}}}", features = ["server", "client-tls"] }
```
The TLS backend is automatically selected based on your target platform:
- **macOS, Windows, iOS**: Uses `native-tls` (system TLS libraries)
- **Linux, Unix, other platforms**: Uses `openssl`
See https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section for how to use features in your `Cargo.toml`.
## Documentation for API Endpoints

View File

@@ -45,17 +45,17 @@ struct Cli {
server_address: String,
/// Path to the client private key if using client-side TLS authentication
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
#[cfg(all(feature = "client-tls", not(any(target_os = "macos", target_os = "windows", target_os = "ios"))))]
#[clap(long, requires_all(&["client_certificate", "server_certificate"]))]
client_key: Option<String>,
/// Path to the client's public certificate associated with the private key
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
#[cfg(all(feature = "client-tls", not(any(target_os = "macos", target_os = "windows", target_os = "ios"))))]
#[clap(long, requires_all(&["client_key", "server_certificate"]))]
client_certificate: Option<String>,
/// Path to CA certificate used to authenticate the server
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
#[cfg(all(feature = "client-tls", not(any(target_os = "macos", target_os = "windows", target_os = "ios"))))]
#[clap(long)]
server_certificate: Option<String>,
@@ -130,7 +130,8 @@ enum Operation {
{{/apiInfo}}
}
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
// On Linux/Unix with OpenSSL (client-tls feature), support certificate pinning and mutual TLS
#[cfg(all(feature = "client-tls", not(any(target_os = "macos", target_os = "windows", target_os = "ios"))))]
fn create_client(args: &Cli, context: ClientContext) -> Result<Box<dyn ApiNoContext<ClientContext>>> {
if args.client_certificate.is_some() {
debug!("Using mutual TLS");
@@ -156,8 +157,15 @@ fn create_client(args: &Cli, context: ClientContext) -> Result<Box<dyn ApiNoCont
}
}
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))]
// On macOS/Windows/iOS or without client-tls feature, use simple client (no cert pinning/mutual TLS)
#[cfg(any(
not(feature = "client-tls"),
all(feature = "client-tls", any(target_os = "macos", target_os = "windows", target_os = "ios"))
))]
fn create_client(args: &Cli, context: ClientContext) -> Result<Box<dyn ApiNoContext<ClientContext>>> {
// Client::try_new() automatically detects the URL scheme (http:// or https://)
// and creates the appropriate client.
// Note: Certificate pinning and mutual TLS are only available on Linux/Unix with OpenSSL
let client =
Client::try_new(&args.server_address).context("Failed to create HTTP(S) client")?;
Ok(Box::new(client.with_context(context)))

View File

@@ -118,10 +118,17 @@ impl<Connector, C> Client<
}
}
#[cfg(all(feature = "client-tls", any(target_os = "macos", target_os = "windows", target_os = "ios")))]
type HyperHttpsConnector = hyper_tls::HttpsConnector<hyper_util::client::legacy::connect::HttpConnector>;
#[cfg(all(feature = "client-tls", not(any(target_os = "macos", target_os = "windows", target_os = "ios"))))]
type HyperHttpsConnector = hyper_openssl::client::legacy::HttpsConnector<hyper_util::client::legacy::connect::HttpConnector>;
#[derive(Debug, Clone)]
pub enum HyperClient {
Http(hyper_util::client::legacy::Client<hyper_util::client::legacy::connect::HttpConnector, BoxBody<Bytes, Infallible>>),
Https(hyper_util::client::legacy::Client<HttpsConnector, BoxBody<Bytes, Infallible>>),
#[cfg(feature = "client-tls")]
Https(hyper_util::client::legacy::Client<HyperHttpsConnector, BoxBody<Bytes, Infallible>>),
}
impl Service<Request<BoxBody<Bytes, Infallible>>> for HyperClient {
@@ -132,7 +139,8 @@ impl Service<Request<BoxBody<Bytes, Infallible>>> for HyperClient {
fn call(&self, req: Request<BoxBody<Bytes, Infallible>>) -> Self::Future {
match self {
HyperClient::Http(client) => client.request(req),
HyperClient::Https(client) => client.request(req)
#[cfg(feature = "client-tls")]
HyperClient::Https(client) => client.request(req),
}
}
}
@@ -158,11 +166,17 @@ impl<C> Client<DropContextService<HyperClient, C>, C> where
"http" => {
HyperClient::Http(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector.build()))
},
#[cfg(feature = "client-tls")]
"https" => {
let connector = connector.https()
.build()
.map_err(ClientInitError::SslError)?;
HyperClient::Https(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector))
let https_connector = connector
.https()
.build()
.map_err(ClientInitError::SslError)?;
HyperClient::Https(hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()).build(https_connector))
},
#[cfg(not(feature = "client-tls"))]
"https" => {
return Err(ClientInitError::TlsNotEnabled);
},
_ => {
return Err(ClientInitError::InvalidScheme);
@@ -206,12 +220,13 @@ impl<C> Client<
}
}
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))]
#[cfg(all(feature = "client-tls", any(target_os = "macos", target_os = "windows", target_os = "ios")))]
type HttpsConnector = hyper_tls::HttpsConnector<hyper_util::client::legacy::connect::HttpConnector>;
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
#[cfg(all(feature = "client-tls", not(any(target_os = "macos", target_os = "windows", target_os = "ios"))))]
type HttpsConnector = hyper_openssl::client::legacy::HttpsConnector<hyper_util::client::legacy::connect::HttpConnector>;
#[cfg(feature = "client-tls")]
impl<C> Client<
DropContextService<
hyper_util::service::TowerToHyperService<
@@ -226,10 +241,11 @@ impl<C> Client<
> where
C: Clone + Send + Sync + 'static
{
/// Create a client with a TLS connection to the server
/// Create a client with a TLS connection to the server.
///
/// # Arguments
/// * `base_path` - base path of the client API, i.e. "<http://www.my-api-implementation.com>"
/// * `base_path` - base path of the client API, i.e. "<https://www.my-api-implementation.com>"
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))]
pub fn try_new_https(base_path: &str) -> Result<Self, ClientInitError>
{
let https_connector = Connector::builder()
@@ -239,10 +255,24 @@ impl<C> Client<
Self::try_new_with_connector(base_path, Some("https"), https_connector)
}
/// Create a client with a TLS connection to the server using a pinned certificate
/// Create a client with a TLS connection to the server using OpenSSL via swagger.
///
/// # Arguments
/// * `base_path` - base path of the client API, i.e. "<http://www.my-api-implementation.com>"
/// * `base_path` - base path of the client API, i.e. "<https://www.my-api-implementation.com>"
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
pub fn try_new_https(base_path: &str) -> Result<Self, ClientInitError>
{
let https_connector = Connector::builder()
.https()
.build()
.map_err(ClientInitError::SslError)?;
Self::try_new_with_connector(base_path, Some("https"), https_connector)
}
/// Create a client with a TLS connection to the server using a pinned certificate.
///
/// # Arguments
/// * `base_path` - base path of the client API, i.e. "<https://www.my-api-implementation.com>"
/// * `ca_certificate` - Path to CA certificate used to authenticate the server
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
pub fn try_new_https_pinned<CA>(
@@ -263,7 +293,7 @@ impl<C> Client<
/// Create a client with a mutually authenticated TLS connection to the server.
///
/// # Arguments
/// * `base_path` - base path of the client API, i.e. "<http://www.my-api-implementation.com>"
/// * `base_path` - base path of the client API, i.e. "<https://www.my-api-implementation.com>"
/// * `ca_certificate` - Path to CA certificate used to authenticate the server
/// * `client_key` - Path to the client private key
/// * `client_certificate` - Path to the client's public certificate associated with the private key
@@ -325,12 +355,15 @@ pub enum ClientInitError {
/// Missing Hostname
MissingHost,
/// HTTPS requested but TLS features not enabled
TlsNotEnabled,
/// SSL Connection Error
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))]
#[cfg(all(feature = "client-tls", any(target_os = "macos", target_os = "windows", target_os = "ios")))]
SslError(native_tls::Error),
/// SSL Connection Error
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
#[cfg(all(feature = "client-tls", not(any(target_os = "macos", target_os = "windows", target_os = "ios"))))]
SslError(openssl::error::ErrorStack),
}

View File

@@ -115,17 +115,33 @@ fn main() {
let context: ClientContext =
swagger::make_context!(ContextBuilder, EmptyContext, auth_data, XSpanIdString::default());
let mut client : Box<dyn ApiNoContext<ClientContext>> = if is_https {
// Using Simple HTTPS
let client = Box::new(Client::try_new_https(&base_url)
.expect("Failed to create HTTPS client"));
Box::new(client.with_context(context))
} else {
// Using HTTP
let client = Box::new(Client::try_new_http(
&base_url)
.expect("Failed to create HTTP client"));
Box::new(client.with_context(context))
let mut client : Box<dyn ApiNoContext<ClientContext>> = {
#[cfg(feature = "client-tls")]
{
if is_https {
// Using HTTPS with native-tls
let client = Box::new(Client::try_new_https(&base_url)
.expect("Failed to create HTTPS client"));
Box::new(client.with_context(context))
} else {
// Using HTTP
let client = Box::new(Client::try_new_http(&base_url)
.expect("Failed to create HTTP client"));
Box::new(client.with_context(context))
}
}
#[cfg(not(feature = "client-tls"))]
{
if is_https {
panic!("HTTPS requested but TLS support not enabled. \
Enable the 'client-tls' feature to use HTTPS.");
}
// Using HTTP only
let client = Box::new(Client::try_new_http(&base_url)
.expect("Failed to create HTTP client"));
Box::new(client.with_context(context))
}
};
let mut rt = tokio::runtime::Runtime::new().unwrap();

View File

@@ -97,16 +97,17 @@ impl<C> Client<DropContextService<hyper_util::service::TowerToHyperService<hyper
}
}
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))]
#[cfg(all(feature = "client-tls", any(target_os = "macos", target_os = "windows", target_os = "ios")))]
type HttpsConnector = hyper_tls::HttpsConnector<hyper_util::client::legacy::connect::HttpConnector>;
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
#[cfg(all(feature = "client-tls", not(any(target_os = "macos", target_os = "windows", target_os = "ios"))))]
type HttpsConnector = hyper_openssl::client::legacy::HttpsConnector<hyper_util::client::legacy::connect::HttpConnector>;
#[cfg(feature = "client-tls")]
impl<C> Client<DropContextService<hyper_util::service::TowerToHyperService<hyper_util::client::legacy::Client<HttpsConnector, BoxBody<Bytes, Infallible>>>, C>, C> where
C: Clone + Send + Sync + 'static
{
/// Create a client with a TLS connection to the server.
/// Create a client with a TLS connection to the server using native-tls.
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))]
pub fn new_https() -> Result<Self, native_tls::Error>
{
@@ -114,7 +115,7 @@ impl<C> Client<DropContextService<hyper_util::service::TowerToHyperService<hyper
Ok(Self::new_with_connector(https_connector))
}
/// Create a client with a TLS connection to the server.
/// Create a client with a TLS connection to the server using OpenSSL.
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
pub fn new_https() -> Result<Self, openssl::error::ErrorStack>
{

View File

@@ -110,7 +110,8 @@ export const setSearchParams = function (url: URL, ...objects: any[]) {
* This function will run for every key-value pair encountered by JSON.stringify while traversing an object.
* Converting a set to a string will return an empty object, so an intermediate conversion to an array is required.
*/
export const replaceWithSerializableTypeIfNeeded = function(key: any, value: any) {
// @ts-ignore
export const replaceWithSerializableTypeIfNeeded = function(key: string, value: any) {
if (value instanceof Set) {
return Array.from(value);
} else {

View File

@@ -70,15 +70,15 @@ export function {{classname}}FromJSONTyped(json: any, ignoreDiscriminator: boole
{{#items}}
{{#isDateType}}
if (Array.isArray(json)) {
if (json.every(item => !(isNaN(new Date(json).getTime()))) {
return json.map(value => new Date(json);
if (json.every(item => !(isNaN(new Date(item).getTime())))) {
return json.map(value => new Date(value));
}
}
{{/isDateType}}
{{#isDateTimeType}}
if (Array.isArray(json)) {
if (json.every(item => !(isNaN(new Date(json).getTime()))) {
return json.map(value => new Date(json);
if (json.every(item => !(isNaN(new Date(item).getTime())))) {
return json.map(value => new Date(value));
}
}
{{/isDateTimeType}}
@@ -188,14 +188,14 @@ export function {{classname}}ToJSONTyped(value?: {{classname}} | null, ignoreDis
{{#isDateType}}
if (Array.isArray(value)) {
if (value.every(item => item instanceof Date) {
return value.map(value => value.toISOString().substring(0,10)));
return value.map(value => value.toISOString().substring(0,10));
}
}
{{/isDateType}}
{{#isDateTimeType}}
if (Array.isArray(value)) {
if (value.every(item => item instanceof Date) {
return value.map(value => value.toISOString();
if (value.every(item => item instanceof Date)) {
return value.map(item => item.toISOString());
}
}
{{/isDateTimeType}}

View File

@@ -216,6 +216,11 @@ export class RequestContext {
export interface ResponseBody {
text(): Promise<string>;
binary(): Promise<{{{fileContentDataType}}}>;
{{#platforms}}
{{#node}}
stream(): ReadableStream<Uint8Array> | null;
{{/node}}
{{/platforms}}
}
/**
@@ -253,6 +258,14 @@ export class SelfDecodingBody implements ResponseBody {
{{/deno}}
{{/platforms}}
}
{{#platforms}}
{{#node}}
stream(): ReadableStream<Uint8Array> | null {
return null;
}
{{/node}}
{{/platforms}}
}
export class ResponseContext {

View File

@@ -38,7 +38,8 @@ export class IsomorphicFetchHttpLibrary implements HttpLibrary {
{{#node}}
const body = {
text: () => resp.text(),
binary: () => resp.buffer()
binary: () => resp.buffer(),
stream: () => resp.body
};
{{/node}}
{{^node}}

View File

@@ -44,7 +44,7 @@
{{#fetch-api}}
{{#platforms}}
{{#node}}
"undici": "^7.16.0",
"undici": "^7.18.2",
{{/node}}
{{#browser}}
"whatwg-fetch": "^3.0.0",

View File

@@ -1306,6 +1306,59 @@ public class OpenAPINormalizerTest {
assertNotNull(inlinePropertyAfter.getProperties().get("nestedNumber"));
}
@Test
public void testSortModelProperties() {
// Create a schema with properties in non-alphabetical order
Schema schema = new ObjectSchema()
.addProperty("zebra", new StringSchema())
.addProperty("apple", new StringSchema())
.addProperty("mango", new IntegerSchema());
OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("TestModel", schema);
// Verify original order (LinkedHashMap preserves insertion order)
List<String> originalOrder = new ArrayList<>(schema.getProperties().keySet());
assertEquals(originalOrder.get(0), "zebra");
assertEquals(originalOrder.get(1), "apple");
assertEquals(originalOrder.get(2), "mango");
// Apply normalizer with SORT_MODEL_PROPERTIES=true
Map<String, String> options = new HashMap<>();
options.put("SORT_MODEL_PROPERTIES", "true");
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
openAPINormalizer.normalize();
// Verify properties are now sorted alphabetically
Schema normalizedSchema = openAPI.getComponents().getSchemas().get("TestModel");
List<String> sortedOrder = new ArrayList<>(normalizedSchema.getProperties().keySet());
assertEquals(sortedOrder.get(0), "apple");
assertEquals(sortedOrder.get(1), "mango");
assertEquals(sortedOrder.get(2), "zebra");
}
@Test
public void testSortModelPropertiesDisabledByDefault() {
// Create a schema with properties in non-alphabetical order
Schema schema = new ObjectSchema()
.addProperty("zebra", new StringSchema())
.addProperty("apple", new StringSchema())
.addProperty("mango", new IntegerSchema());
OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("TestModel", schema);
// Apply normalizer without SORT_MODEL_PROPERTIES (default is false)
Map<String, String> options = new HashMap<>();
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
openAPINormalizer.normalize();
// Verify properties retain original order
Schema normalizedSchema = openAPI.getComponents().getSchemas().get("TestModel");
List<String> order = new ArrayList<>(normalizedSchema.getProperties().keySet());
assertEquals(order.get(0), "zebra");
assertEquals(order.get(1), "apple");
assertEquals(order.get(2), "mango");
}
public static class RemoveRequiredNormalizer extends OpenAPINormalizer {
public RemoveRequiredNormalizer(OpenAPI openAPI, Map<String, String> inputRules) {

View File

@@ -461,4 +461,27 @@ public class GoClientCodegenTest {
TestUtils.assertFileContains(apiPath, defaultEnumArrayString);
TestUtils.assertFileContains(apiPath, defaultValueString);
}
@Test
public void testEscapingInExamples() throws IOException {
File output = Files.createTempDirectory("test").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("go")
.setInputSpec("src/test/resources/3_0/go/petstore-with-special-chars-in-examples.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
files.forEach(File::deleteOnExit);
Path docPath = Paths.get(output + "/docs/TestAPI.md");
// Verify that quotes are properly escaped in parameter examples
TestUtils.assertFileContains(docPath, "stringWithQuotes := \"John \\\"Johnny\\\" Doe\"");
// Verify that backslashes are properly escaped in parameter examples
TestUtils.assertFileContains(docPath, "stringWithBackslash := \"C:\\\\path\\\\to\\\\file\"");
// Verify that quotes are properly escaped in email parameter examples
TestUtils.assertFileContains(docPath, "emailWithQuotes := \"test\\\"user@example.com\"");
}
}

View File

@@ -649,6 +649,10 @@ public class KotlinClientCodegenModelTest {
// base properties are present
TestUtils.assertFileContains(animalKt, "val id");
TestUtils.assertFileContains(animalKt, "val optionalProperty");
// base array with unique items = false is correctly handled as List
TestUtils.assertFileContains(animalKt, "val stringArray: kotlin.collections.List<kotlin.String>");
// base array with unique items = true is correctly handled as Set
TestUtils.assertFileContains(animalKt, "val stringSet: kotlin.collections.Set<kotlin.String>");
// base doesn't contain discriminator
TestUtils.assertFileNotContains(animalKt, "val discriminator");
@@ -658,6 +662,10 @@ public class KotlinClientCodegenModelTest {
// derived properties are overridden
TestUtils.assertFileContains(birdKt, "override val id");
TestUtils.assertFileContains(birdKt, "override val optionalProperty");
// derived array with unique items = false is correctly handled as List and with override
TestUtils.assertFileContains(birdKt, "override val stringArray: kotlin.collections.List<kotlin.String>");
// derived array with unique items = true is correctly handled as Set and with override
TestUtils.assertFileContains(birdKt, "override val stringSet: kotlin.collections.Set<kotlin.String>");
// derived doesn't contain disciminator
TestUtils.assertFileNotContains(birdKt, "val discriminator");
}

View File

@@ -89,6 +89,8 @@ public class KotlinSpringServerCodegenTest {
// base properties are present
TestUtils.assertFileContains(animalKt, "val id");
TestUtils.assertFileContains(animalKt, "val optionalProperty");
TestUtils.assertFileContains(animalKt, "val stringArray: kotlin.collections.List<kotlin.String>");
TestUtils.assertFileContains(animalKt, "val stringSet: kotlin.collections.Set<kotlin.String>");
// base doesn't contain discriminator
TestUtils.assertFileNotContains(animalKt, "val discriminator");
@@ -98,6 +100,8 @@ public class KotlinSpringServerCodegenTest {
// derived properties are overridden
TestUtils.assertFileContains(birdKt, "override val id");
TestUtils.assertFileContains(birdKt, "override val optionalProperty");
TestUtils.assertFileContains(birdKt, "override val stringArray: kotlin.collections.List<kotlin.String>");
TestUtils.assertFileContains(birdKt, "override val stringSet: kotlin.collections.Set<kotlin.String>");
// derived doesn't contain disciminator
TestUtils.assertFileNotContains(birdKt, "val discriminator");
}

View File

@@ -29,6 +29,7 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;
@@ -146,4 +147,33 @@ public class PhpNextgenClientCodegenTest {
Assert.assertListNotContains(modelContent, a -> a.equals("$color = self::COLOR_UNKNOWN_DEFAULT_OPEN_API;"), "");
Assert.assertListContains(modelContent, a -> a.equalsIgnoreCase("\"Invalid value '%s' for 'color', must be one of '%s'\","), "");
}
@Test
public void testDifferentResponseSchemasWithEmpty() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
OpenAPI openAPI = new OpenAPIParser()
.readLocation("src/test/resources/bugs/issue_22817.yaml", null, new ParseOptions())
.getOpenAPI();
codegen.setOutputDir(output.getAbsolutePath());
ClientOptInput input = new ClientOptInput()
.openAPI(openAPI)
.config(codegen);
DefaultGenerator generator = new DefaultGenerator();
Map<String, File> files = generator.opts(input).generate().stream()
.collect(Collectors.toMap(File::getName, Function.identity()));
List<String> modelContent = Files
.readAllLines(files.get("DefaultApi.php").toPath())
.stream()
.map(String::trim)
.collect(Collectors.toList());
Assert.assertListContains(modelContent, a -> a.equals("): int|string|null"), "Expected to find nullable return type declaration.");
Assert.assertListNotContains(modelContent, a -> a.equals("): ?int|string"), "Expected to not find invalid union type with '?'.");
}
}

View File

@@ -51,6 +51,7 @@ import java.util.Map;
import static org.openapitools.codegen.TestUtils.createCodegenModelWrapper;
import static org.openapitools.codegen.languages.ProtobufSchemaCodegen.USE_SIMPLIFIED_ENUM_NAMES;
import static org.testng.Assert.assertEquals;
import static org.openapitools.codegen.languages.ProtobufSchemaCodegen.EXTRACT_ENUMS_TO_SEPARATE_FILES;
import static org.openapitools.codegen.languages.ProtobufSchemaCodegen.START_ENUMS_WITH_UNSPECIFIED;
public class ProtobufSchemaCodegenTest {
@@ -361,6 +362,73 @@ public class ProtobufSchemaCodegenTest {
Assert.assertEquals(enumVars1.get(1).get("isString"), false);
}
@Test(description = "Support multiple level of inheritance for discriminator - ensures properties from indirect children are included")
public void testCodeGenWithAllOfDiscriminatorMultipleLevels() throws IOException {
// set line break to \n across all platforms
System.setProperty("line.separator", "\n");
File output = Files.createTempDirectory("test").toFile();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("protobuf-schema")
.setInputSpec("src/test/resources/3_0/allOf_composition_discriminator_multiple_inheritance.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
// Verify Animal proto file (discriminator parent)
TestUtils.ensureContainsFile(files, output, "models/animal.proto");
Path animalPath = Paths.get(output + "/models/animal.proto");
String animalContent = new String(Files.readAllBytes(animalPath), StandardCharsets.UTF_8);
// Properties from discriminated classes should be included in Animal:
// From Dog (direct child in discriminator mapping): bark
Assert.assertTrue(animalContent.contains("string bark"), "Animal should contain 'bark' property from Dog");
// From Feline (intermediate parent, NOT in discriminator mapping): name, furColor
Assert.assertTrue(animalContent.contains("string name"), "Animal should contain 'name' property from Feline");
Assert.assertTrue(animalContent.contains("string fur_color"), "Animal should contain 'fur_color' property from Feline");
// From Cat (indirect child through Feline, IN discriminator mapping): isIndoor, careDetails
Assert.assertTrue(animalContent.contains("bool is_indoor"), "Animal should contain 'is_indoor' property from Cat (indirect child)");
Assert.assertTrue(animalContent.contains("CareDetails care_details"), "Animal should contain 'care_details' property from Cat (indirect child)");
assertFileEquals(animalPath, Paths.get("src/test/resources/3_0/protobuf-schema/animal.proto"));
// Verify Cat proto file (indirect child in discriminator mapping)
TestUtils.ensureContainsFile(files, output, "models/cat.proto");
Path catPath = Paths.get(output + "/models/cat.proto");
String catContent = new String(Files.readAllBytes(catPath), StandardCharsets.UTF_8);
// Cat should import Animal (the discriminator parent), not Feline (its immediate allOf parent)
Assert.assertTrue(catContent.contains("import public \"models/animal.proto\";"),
"Cat should import Animal (discriminator parent)");
// Cat should also import CareDetails (its dependency)
Assert.assertTrue(catContent.contains("import public \"models/care_details.proto\";"),
"Cat should import CareDetails");
// Verify Feline proto file (intermediate parent, NOT in discriminator mapping)
TestUtils.ensureContainsFile(files, output, "models/feline.proto");
Path felinePath = Paths.get(output + "/models/feline.proto");
String felineContent = new String(Files.readAllBytes(felinePath), StandardCharsets.UTF_8);
// According to requirements: Feline inherits from Animal but is NOT in discriminator mapping
// So Feline should NOT import Animal
Assert.assertFalse(felineContent.contains("import public \"models/animal.proto\";"),
"Feline should NOT import Animal (not in discriminator mapping)");
// Verify Dog proto file (direct child in discriminator mapping)
TestUtils.ensureContainsFile(files, output, "models/dog.proto");
Path dogPath = Paths.get(output + "/models/dog.proto");
String dogContent = new String(Files.readAllBytes(dogPath), StandardCharsets.UTF_8);
// Dog should import Animal (the discriminator parent)
Assert.assertTrue(dogContent.contains("import public \"models/animal.proto\";"),
"Dog should import Animal (discriminator parent)");
output.deleteOnExit();
}
@SuppressWarnings("unchecked")
@Test(description = "Validate that enums in arrays are treated as complex types")
public void enumInArrayIsTreatedAsComplexType() {
@@ -406,4 +474,591 @@ public class ProtobufSchemaCodegenTest {
final CodegenProperty property = cm.vars.get(0);
Assert.assertEquals(property.baseName, "colorMap");
}
@Test(description = "Validate that a model referenced multiple times is imported only once in generated protobuf files")
public void testModelImportedOnlyOnce() throws IOException {
// set line break to \n across all platforms
System.setProperty("line.separator", "\n");
File output = Files.createTempDirectory("test").toFile();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("protobuf-schema")
.setInputSpec("src/test/resources/3_0/protobuf-schema/model_imported_once.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
// Check that the main model file was generated
TestUtils.ensureContainsFile(files, output, "models/model.proto");
Path modelPath = Paths.get(output + "/models/model.proto");
String modelContent = new String(Files.readAllBytes(modelPath), StandardCharsets.UTF_8);
// Count occurrences of the import statement for model A (using "public" keyword as generated)
String importStatement = "import public \"models/a.proto\";";
int importCount = countOccurrences(modelContent, importStatement);
// Assert that model A is imported exactly once despite being used in:
// - direct field in Model (directA)
// - field in SubModel which is nested in Model (SubModel.aReference)
Assert.assertEquals(importCount, 1, "Model A should be imported exactly once in model.proto");
// Check the SubModel file - it also references A directly
TestUtils.ensureContainsFile(files, output, "models/sub_model.proto");
Path subModelPath = Paths.get(output + "/models/sub_model.proto");
String subModelContent = new String(Files.readAllBytes(subModelPath), StandardCharsets.UTF_8);
int subModelImportCount = countOccurrences(subModelContent, importStatement);
Assert.assertEquals(subModelImportCount, 1, "Model A should be imported exactly once in sub_model.proto");
// Check the ExtensibleModel file
TestUtils.ensureContainsFile(files, output, "models/extensible_model.proto");
Path extensiblePath = Paths.get(output + "/models/extensible_model.proto");
String extensibleContent = new String(Files.readAllBytes(extensiblePath), StandardCharsets.UTF_8);
// Count occurrences in ExtensibleModel
int extensibleImportCount = countOccurrences(extensibleContent, importStatement);
// Assert that model A is imported exactly once in ExtensibleModel despite being used in:
// - direct field in ExtensibleModel (extensibleA)
// - field in ChildModel_1 (childA) which extends ExtensibleModel via discriminator
// - field in ChildModel_2 (directA) which also extends ExtensibleModel via discriminator
Assert.assertEquals(extensibleImportCount, 1, "Model A should be imported exactly once in extensible_model.proto");
output.deleteOnExit();
}
private int countOccurrences(String content, String substring) {
int count = 0;
int index = 0;
while ((index = content.indexOf(substring, index)) != -1) {
count++;
index += substring.length();
}
return count;
}
@Test(description = "Validate that enums are extracted to separate files when extractEnumsToSeparateFiles option is enabled")
public void testExtractEnumsToSeparateFiles() throws IOException {
// set line break to \n across all platforms
System.setProperty("line.separator", "\n");
File output = Files.createTempDirectory("test").toFile();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("protobuf-schema")
.setInputSpec("src/test/resources/3_0/protobuf-schema/extracted_enum.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"))
.addAdditionalProperty(EXTRACT_ENUMS_TO_SEPARATE_FILES, true);
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
// Check that separate enum files were generated
// With the new naming scheme, inline enum names include the parent model prefix
TestUtils.ensureContainsFile(files, output, "models/separated_enum.proto");
TestUtils.ensureContainsFile(files, output, "models/model_with_enums_inline_enum_property.proto");
TestUtils.ensureContainsFile(files, output, "models/all_of_model_with_enums_another_inline_enum_property.proto");
// Check that the model file was generated
TestUtils.ensureContainsFile(files, output, "models/model_with_enums.proto");
Path modelPath = Paths.get(output + "/models/model_with_enums.proto");
String modelContent = new String(Files.readAllBytes(modelPath), StandardCharsets.UTF_8);
// Verify that enums are NOT defined inline in the model
Assert.assertFalse(modelContent.contains("enum Inline_enum_property"),
"Inline enum should be extracted to separate file");
// Verify that the model imports the separated enum files
Assert.assertTrue(modelContent.contains("import public \"models/separated_enum.proto\";"),
"Model should import the separated enum file");
Assert.assertTrue(modelContent.contains("import public \"models/model_with_enums_inline_enum_property.proto\";"),
"Model should import the inline enum file with parent model prefix");
// Verify that the model uses the correct enum reference with .Enum suffix
// With the new naming scheme, inline enums use ParentModelName_FieldName format
Assert.assertTrue(modelContent.contains("ModelWithEnums_InlineEnumProperty.Enum"),
"Model should reference extracted enum with .Enum suffix and parent model prefix");
// Check the AllOfModel file
TestUtils.ensureContainsFile(files, output, "models/all_of_model_with_enums.proto");
Path allOfModelPath = Paths.get(output + "/models/all_of_model_with_enums.proto");
String allOfModelContent = new String(Files.readAllBytes(allOfModelPath), StandardCharsets.UTF_8);
// Verify that the allOf model imports the separated enum files
Assert.assertTrue(allOfModelContent.contains("import public \"models/all_of_model_with_enums_another_inline_enum_property.proto\";"),
"AllOf model should import its inline enum file with parent model prefix");
// Verify the separated enum file content
Path separatedEnumPath = Paths.get(output + "/models/separated_enum.proto");
String separatedEnumContent = new String(Files.readAllBytes(separatedEnumPath), StandardCharsets.UTF_8);
Assert.assertTrue(separatedEnumContent.contains("package openapitools;"),
"Separated enum file should contain a valid package declaration");
Assert.assertTrue(separatedEnumContent.contains("message SeparatedEnum"),
"Separated enum file should contain the message wrapper");
Assert.assertTrue(separatedEnumContent.contains("enum Enum {"),
"Separated enum file should contain inner Enum definition");
Assert.assertTrue(separatedEnumContent.contains("SEPARATED_ENUM_VALUE1"),
"Separated enum should contain SEPARATED_ENUM_VALUE1");
Assert.assertTrue(separatedEnumContent.contains("SEPARATED_ENUM_VALUE2"),
"Separated enum should contain SEPARATED_ENUM_VALUE2");
// Verify the inline enum file content - uses parent model name prefix
Path inlineEnumPath = Paths.get(output + "/models/model_with_enums_inline_enum_property.proto");
String inlineEnumContent = new String(Files.readAllBytes(inlineEnumPath), StandardCharsets.UTF_8);
Assert.assertTrue(inlineEnumContent.contains("package openapitools;"),
"Inline enum file should contain a valid package declaration");
Assert.assertTrue(inlineEnumContent.contains("message ModelWithEnums_InlineEnumProperty"),
"Inline enum file should contain the message wrapper with parent model prefix");
Assert.assertTrue(inlineEnumContent.contains("enum Enum {"),
"Inline enum file should contain inner Enum definition");
// Note: Enum values keep the prefixes from the original field name, not parent+field
// since they are already scoped within the message wrapper
Assert.assertTrue(inlineEnumContent.contains("INLINE_ENUM_PROPERTY_VALUE2"),
"Inline enum should contain enum value");
Assert.assertTrue(inlineEnumContent.contains("INLINE_ENUM_PROPERTY_VALUE3"),
"Inline enum should contain enum value");
Assert.assertTrue(inlineEnumContent.contains("INLINE_ENUM_PROPERTY_VALUE4"),
"Inline enum should contain enum value");
output.deleteOnExit();
}
@Test(description = "Validate that enums are extracted to separate files when extractEnumsToSeparateFiles option is enabled")
public void testExtractEnumsToSeparateFilesWithOtherEnumOptions() throws IOException {
// set line break to \n across all platforms
System.setProperty("line.separator", "\n");
File output = Files.createTempDirectory("test").toFile();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("protobuf-schema")
.setInputSpec("src/test/resources/3_0/protobuf-schema/extracted_enum.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"))
.addAdditionalProperty("removeEnumValuePrefix", false)
.addAdditionalProperty(START_ENUMS_WITH_UNSPECIFIED, true)
.addAdditionalProperty(USE_SIMPLIFIED_ENUM_NAMES, true)
.addAdditionalProperty(EXTRACT_ENUMS_TO_SEPARATE_FILES, true);
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
// Check that separate enum files were generated with parent model prefix
TestUtils.ensureContainsFile(files, output, "models/separated_enum.proto");
TestUtils.ensureContainsFile(files, output, "models/model_with_enums_inline_enum_property.proto");
TestUtils.ensureContainsFile(files, output, "models/all_of_model_with_enums_another_inline_enum_property.proto");
// Check that the model file was generated
TestUtils.ensureContainsFile(files, output, "models/model_with_enums.proto");
Path modelPath = Paths.get(output + "/models/model_with_enums.proto");
String modelContent = new String(Files.readAllBytes(modelPath), StandardCharsets.UTF_8);
// Verify that enums are NOT defined inline in the model
Assert.assertFalse(modelContent.contains("enum Inline_enum_property"),
"Inline enum should be extracted to separate file");
// Verify that the model imports the separated enum files
Assert.assertTrue(modelContent.contains("import public \"models/separated_enum.proto\";"),
"Model should import the separated enum file");
Assert.assertTrue(modelContent.contains("import public \"models/model_with_enums_inline_enum_property.proto\";"),
"Model should import the inline enum file with parent model prefix");
// Verify that the model uses the correct enum reference with .Enum suffix
// With the new naming scheme, inline enums use ParentModelName_FieldName format
Assert.assertTrue(modelContent.contains("ModelWithEnums_InlineEnumProperty.Enum"),
"Model should reference extracted enum with .Enum suffix and parent model prefix");
// Check the AllOfModel file
TestUtils.ensureContainsFile(files, output, "models/all_of_model_with_enums.proto");
Path allOfModelPath = Paths.get(output + "/models/all_of_model_with_enums.proto");
String allOfModelContent = new String(Files.readAllBytes(allOfModelPath), StandardCharsets.UTF_8);
// Verify that the allOf model imports the separated enum files
Assert.assertTrue(allOfModelContent.contains("import public \"models/all_of_model_with_enums_another_inline_enum_property.proto\";"),
"AllOf model should import its inline enum file with parent model prefix");
// Verify the separated enum file content
Path separatedEnumPath = Paths.get(output + "/models/separated_enum.proto");
String separatedEnumContent = new String(Files.readAllBytes(separatedEnumPath), StandardCharsets.UTF_8);
Assert.assertTrue(separatedEnumContent.contains("package openapitools;"),
"Separated enum file should contain a valid package declaration");
Assert.assertTrue(separatedEnumContent.contains("message SeparatedEnum"),
"Separated enum file should contain the message wrapper");
Assert.assertTrue(separatedEnumContent.contains("enum Enum {"),
"Separated enum file should contain inner Enum definition");
Assert.assertTrue(separatedEnumContent.contains("UNSPECIFIED"),
"Separated enum should contain UNSPECIFIED");
Assert.assertTrue(separatedEnumContent.contains("VALUE1"),
"Separated enum should contain VALUE1");
Assert.assertTrue(separatedEnumContent.contains("VALUE2"),
"Separated enum should contain VALUE2");
// Verify the inline enum file content - uses parent model name prefix
Path inlineEnumPath = Paths.get(output + "/models/model_with_enums_inline_enum_property.proto");
String inlineEnumContent = new String(Files.readAllBytes(inlineEnumPath), StandardCharsets.UTF_8);
Assert.assertTrue(inlineEnumContent.contains("package openapitools;"),
"Inline enum file should contain a valid package declaration");
Assert.assertTrue(inlineEnumContent.contains("message ModelWithEnums_InlineEnumProperty"),
"Inline enum file should contain the message wrapper with parent model prefix");
Assert.assertTrue(inlineEnumContent.contains("enum Enum {"),
"Inline enum file should contain inner Enum definition");
Assert.assertTrue(inlineEnumContent.contains("UNSPECIFIED"),
"Inline enum should contain UNSPECIFIED");
// With simplified names, enum values don't have prefixes, just the base values
Assert.assertTrue(inlineEnumContent.contains("VALUE2"),
"Inline enum should contain enum value");
Assert.assertTrue(inlineEnumContent.contains("VALUE3"),
"Inline enum should contain enum value");
Assert.assertTrue(inlineEnumContent.contains("VALUE4"),
"Inline enum should contain enum value");
//output.deleteOnExit();
}
@Test(description = "Test toModelImport with various input formats")
public void testToModelImportVariations() {
final ProtobufSchemaCodegen codegen = new ProtobufSchemaCodegen();
codegen.setModelPackage("models");
// Normal case
Assert.assertEquals(codegen.toModelImport("Pet"), "models/pet");
// Already prefixed - should not duplicate
Assert.assertEquals(codegen.toModelImport("models/pet"), "models/pet");
// With different casing
Assert.assertEquals(codegen.toModelImport("PetStore"), "models/pet_store");
// With numbers
Assert.assertEquals(codegen.toModelImport("Pet123"), "models/pet123");
// Empty model package
codegen.setModelPackage("");
Assert.assertEquals(codegen.toModelImport("Pet"), "Pet");
}
@Test(description = "Validate that enum imports are added to discriminator parent when extractEnumsToSeparateFiles is enabled")
public void testDiscriminatorWithExtractedEnums() throws IOException {
// set line break to \n across all platforms
String originalLineSeparator = System.getProperty("line.separator");
try {
System.setProperty("line.separator", "\n");
File output = Files.createTempDirectory("test").toFile();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("protobuf-schema")
.setInputSpec("src/test/resources/3_0/protobuf-schema/extracted_enum.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"))
.addAdditionalProperty(EXTRACT_ENUMS_TO_SEPARATE_FILES, true);
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
// Check that the discriminator parent file was generated
TestUtils.ensureContainsFile(files, output, "models/discriminated_model.proto");
Path discriminatorPath = Paths.get(output + "/models/discriminated_model.proto");
String discriminatorContent = new String(Files.readAllBytes(discriminatorPath), StandardCharsets.UTF_8);
// The discriminator parent should have properties from both children
// From ModelTypeAWithInlineEnum: specificPropertyA, inlineEnumPropertyA
Assert.assertTrue(discriminatorContent.contains("string specific_property_a"),
"Discriminator parent should contain 'specific_property_a' from child A");
// The enum property should be present with the correct .Enum suffix
// With the new naming scheme, inline enums use ParentModelName_FieldName format
Assert.assertTrue(discriminatorContent.contains("ModelTypeAWithInlineEnum_InlineEnumProperty.Enum inline_enum_property"),
"Discriminator parent should contain extracted enum property from child A with .Enum suffix and parent model prefix");
// CRITICAL: The discriminator parent should import the extracted enum file
Assert.assertTrue(discriminatorContent.contains("import public \"models/model_type_a_with_inline_enum_inline_enum_property.proto\";"),
"Discriminator parent MUST import the extracted enum from child A with parent model prefix");
// From ModelTypeBWithInlineEnum: specificPropertyB, referenceEnumPropertyB
Assert.assertTrue(discriminatorContent.contains("string specific_property_b"),
"Discriminator parent should contain 'specific_property_b' from child B");
// Child B references SeparatedEnum (not inline), so it should be imported
Assert.assertTrue(discriminatorContent.contains("import public \"models/separated_enum.proto\";"),
"Discriminator parent should import the separated enum referenced by child B");
// Verify the extracted enum file for inline enum from child A was created
// The file name uses snake_case of the full wrapper message name
TestUtils.ensureContainsFile(files, output, "models/model_type_a_with_inline_enum_inline_enum_property.proto");
Path enumPath = Paths.get(output + "/models/model_type_a_with_inline_enum_inline_enum_property.proto");
String enumContent = new String(Files.readAllBytes(enumPath), StandardCharsets.UTF_8);
Assert.assertTrue(enumContent.contains("message ModelTypeAWithInlineEnum_InlineEnumProperty"),
"Extracted enum file should contain the message wrapper with parent model prefix");
Assert.assertTrue(enumContent.contains("enum Enum {"),
"Extracted enum file should contain inner Enum definition");
// Note: Enum values keep the prefixes from the original field name, not parent+field
// since they are already scoped within the message wrapper
Assert.assertTrue(enumContent.contains("INLINE_ENUM_PROPERTY_VALUE7"),
"Extracted enum should contain enum value");
Assert.assertTrue(enumContent.contains("INLINE_ENUM_PROPERTY_VALUE8"),
"Extracted enum should contain enum value");
output.deleteOnExit();
} finally {
// Restore original property to avoid side effects on other tests
System.setProperty("line.separator", originalLineSeparator);
}
}
@SuppressWarnings("unchecked")
@Test(description = "Validate that referenced enum models are correctly wrapped with .Enum suffix when extractEnumsToSeparateFiles is enabled")
public void testReferencedEnumsWithExtraction() throws IOException {
// set line break to \n across all platforms
String originalLineSeparator = System.getProperty("line.separator");
try {
System.setProperty("line.separator", "\n");
File output = Files.createTempDirectory("test").toFile();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("protobuf-schema")
.setInputSpec("src/test/resources/3_0/protobuf-schema/extracted_enum.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"))
.addAdditionalProperty(EXTRACT_ENUMS_TO_SEPARATE_FILES, true);
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
// Check that the model file was generated
TestUtils.ensureContainsFile(files, output, "models/model_with_enums.proto");
Path modelPath = Paths.get(output + "/models/model_with_enums.proto");
String modelContent = new String(Files.readAllBytes(modelPath), StandardCharsets.UTF_8)
.replace("\r\n", "\n").replace("\r", "\n");
// CRITICAL: The model should have the inline enum property with .Enum suffix
// With the new naming scheme, inline enums use ParentModelName_FieldName format
Assert.assertTrue(modelContent.contains("ModelWithEnums_InlineEnumProperty.Enum inline_enum_property"),
"Model should reference inline extracted enum with .Enum suffix and parent model prefix");
// CRITICAL: The model should have the referenced enum property with .Enum suffix
// This is the bug being fixed - referenced enums should also get wrapped
Assert.assertTrue(modelContent.contains("SeparatedEnum.Enum reference_enum_property"),
"Model should reference referenced enum with .Enum suffix (THIS IS THE FIX)");
// Verify that both enum files are imported
Assert.assertTrue(modelContent.contains("import public \"models/separated_enum.proto\";"),
"Model should import the separated enum file");
Assert.assertTrue(modelContent.contains("import public \"models/model_with_enums_inline_enum_property.proto\";"),
"Model should import the inline enum file with parent model prefix");
// Verify the separated enum file was correctly generated
TestUtils.ensureContainsFile(files, output, "models/separated_enum.proto");
Path separatedEnumPath = Paths.get(output + "/models/separated_enum.proto");
String separatedEnumContent = new String(Files.readAllBytes(separatedEnumPath), StandardCharsets.UTF_8);
Assert.assertTrue(separatedEnumContent.contains("message SeparatedEnum"),
"Separated enum file should contain the message wrapper");
Assert.assertTrue(separatedEnumContent.contains("enum Enum {"),
"Separated enum file should contain inner Enum definition");
// Verify the inline enum file was correctly generated with parent model prefix
TestUtils.ensureContainsFile(files, output, "models/model_with_enums_inline_enum_property.proto");
Path inlineEnumPath = Paths.get(output + "/models/model_with_enums_inline_enum_property.proto");
String inlineEnumContent = new String(Files.readAllBytes(inlineEnumPath), StandardCharsets.UTF_8);
Assert.assertTrue(inlineEnumContent.contains("message ModelWithEnums_InlineEnumProperty"),
"Inline enum file should contain the message wrapper with parent model prefix");
Assert.assertTrue(inlineEnumContent.contains("enum Enum {"),
"Inline enum file should contain inner Enum definition");
output.deleteOnExit();
} finally {
// Restore original property to avoid side effects on other tests
System.setProperty("line.separator", originalLineSeparator);
}
}
@SuppressWarnings("unchecked")
@Test(description = "Validate backward compatibility: extracted_enum.yaml generates inline enums when EXTRACT_ENUMS_TO_SEPARATE_FILES is NOT enabled")
public void testEnumsRemainsInlineWithoutExtraction() throws IOException {
// set line break to \n across all platforms
String originalLineSeparator = System.getProperty("line.separator");
try {
System.setProperty("line.separator", "\n");
File output = Files.createTempDirectory("test").toFile();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("protobuf-schema")
.setInputSpec("src/test/resources/3_0/protobuf-schema/extracted_enum.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
// Check that the model file was generated
TestUtils.ensureContainsFile(files, output, "models/model_with_enums.proto");
Path modelPath = Paths.get(output + "/models/model_with_enums.proto");
String modelContent = new String(Files.readAllBytes(modelPath), StandardCharsets.UTF_8)
.replace("\r\n", "\n").replace("\r", "\n");
// WITHOUT extraction: Enums should be defined INLINE in the model file
// Check for inline enum definitions (not extracted to separate files)
// The inline enum should contain the enum values (not a message wrapper)
Assert.assertTrue(modelContent.contains("enum") && modelContent.contains("VALUE2"),
"Without extraction, inline enums should be defined inline in the model");
// Verify that inline enums use simple type references (NOT wrapped with .Enum)
// When enums are inline, they're referenced as the enum name directly
// (not as ParentModel_FieldName.Enum which is only used for extracted enums)
Assert.assertTrue(!modelContent.contains(".Enum"),
"Without extraction, enum properties should NOT reference .Enum suffix");
// Without extraction: Inline enum files should NOT be generated
// (Note: SeparatedEnum.proto WILL be generated because SeparatedEnum is a top-level schema,
// but inline_enum_property.proto should NOT be generated because it's an inline enum)
List<Path> inlineEnumFiles = new java.util.ArrayList<>();
if (Files.exists(Paths.get(output + "/models/inline_enum_property.proto"))) {
inlineEnumFiles.add(Paths.get(output + "/models/inline_enum_property.proto"));
}
if (Files.exists(Paths.get(output + "/models/another_inline_enum_property.proto"))) {
inlineEnumFiles.add(Paths.get(output + "/models/another_inline_enum_property.proto"));
}
Assert.assertTrue(inlineEnumFiles.isEmpty(),
"Without extraction option enabled, inline enum files should NOT be created as separate files");
// Verify that imports for inline enum files are NOT present
Assert.assertFalse(modelContent.contains("import public \"models/inline_enum_property.proto\""),
"Without extraction, there should be no inline enum file imports");
Assert.assertFalse(modelContent.contains("import public \"models/another_inline_enum_property.proto\""),
"Without extraction, there should be no inline enum file imports");
// Check the AllOfModel file
TestUtils.ensureContainsFile(files, output, "models/all_of_model_with_enums.proto");
Path allOfModelPath = Paths.get(output + "/models/all_of_model_with_enums.proto");
String allOfModelContent = new String(Files.readAllBytes(allOfModelPath), StandardCharsets.UTF_8);
// IMPORTANT: AllOf composition in protobuf has different semantics than OpenAPI allOf.
// In protobuf, allOf models only contain direct properties of the model, not inherited/composed properties.
// This differs from OpenAPI where allOf models would include properties from all composed schemas.
// Therefore, we validate backward compatibility by ensuring:
// 1. The model file is generated (proving structure is correct)
// 2. No .Enum suffix is used (proving extraction mode is OFF - not using extracted enum references)
// 3. Inline enums are defined inline (proving backward compatibility works with inline enums)
Assert.assertTrue(!allOfModelContent.isEmpty(),
"Without extraction option, the allOf model file should be generated");
Assert.assertFalse(allOfModelContent.contains(".Enum"),
"Without extraction option, enums should NOT use .Enum suffix (should be inline)");
Assert.assertTrue(allOfModelContent.contains("enum") && allOfModelContent.contains("VALUE"),
"Without extraction option, model should contain inline enum definitions");
output.deleteOnExit();
} finally {
// Restore original property to avoid side effects on other tests
System.setProperty("line.separator", originalLineSeparator);
}
}
@Test(description = "Validate that enums in arrays are correctly handled with .Enum suffix when extractEnumsToSeparateFiles is enabled")
public void testEnumsInArraysWithExtraction() throws IOException {
// set line break to \n across all platforms
System.setProperty("line.separator", "\n");
File output = Files.createTempDirectory("test").toFile();
System.out.println("EnumsInArrays Temporary output directory: " + output.getAbsolutePath());
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("protobuf-schema")
.setInputSpec("src/test/resources/3_0/protobuf-schema/extracted_enum.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"))
.addAdditionalProperty("removeEnumValuePrefix", false)
.addAdditionalProperty(START_ENUMS_WITH_UNSPECIFIED, true)
.addAdditionalProperty(USE_SIMPLIFIED_ENUM_NAMES, true)
.addAdditionalProperty(EXTRACT_ENUMS_TO_SEPARATE_FILES, true);
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
// Check that the model file was generated
TestUtils.ensureContainsFile(files, output, "models/all_of_model_with_enums.proto");
Path modelPath = Paths.get(output + "/models/all_of_model_with_enums.proto");
String modelContent = new String(Files.readAllBytes(modelPath), StandardCharsets.UTF_8)
.replace("\r\n", "\n").replace("\r", "\n");
// Test Case 1: Array with REFERENCED enum (listOfReferencedEnums)
// Should have .Enum suffix: repeated SeparatedEnum.Enum
// Use regex to validate structure without depending on specific field numbers
java.util.regex.Pattern referencedEnumPattern = java.util.regex.Pattern.compile(
"repeated\\s+SeparatedEnum\\.Enum\\s+list_of_referenced_enums\\s*=\\s*\\d+");
Assert.assertTrue(
referencedEnumPattern.matcher(modelContent).find(),
"Array with referenced enum should use .Enum suffix with pattern: repeated SeparatedEnum.Enum list_of_referenced_enums = <number>");
// Test Case 2: Array with INLINE enum (listOfEnums) - in AllOfModelWithEnums
// Should have .Enum suffix: repeated AllOfModelWithEnums_ListOfEnums.Enum
// Use regex to validate structure without depending on specific field numbers
java.util.regex.Pattern inlineEnumPattern = java.util.regex.Pattern.compile(
"repeated\\s+AllOfModelWithEnums_ListOfEnums\\.Enum\\s+list_of_enums\\s*=\\s*\\d+");
Assert.assertTrue(
inlineEnumPattern.matcher(modelContent).find(),
"Array with inline enum should use .Enum suffix with pattern: repeated AllOfModelWithEnums_ListOfEnums.Enum list_of_enums = <number>");
// Verify the imported enum file for referenced enum exists
TestUtils.ensureContainsFile(files, output, "models/separated_enum.proto");
// Verify the extracted inline enum file for arrays exists
TestUtils.ensureContainsFile(files, output, "models/all_of_model_with_enums_list_of_enums.proto");
Path listOfEnumsPath = Paths.get(output + "/models/all_of_model_with_enums_list_of_enums.proto");
String listOfEnumsContent = new String(Files.readAllBytes(listOfEnumsPath), StandardCharsets.UTF_8)
.replace("\r\n", "\n").replace("\r", "\n");
// Verify the wrapper message structure
Assert.assertTrue(listOfEnumsContent.contains("message AllOfModelWithEnums_ListOfEnums"),
"Extracted inline enum file should contain wrapper message");
Assert.assertTrue(listOfEnumsContent.contains("enum Enum"),
"Wrapper message should contain inner Enum");
Assert.assertTrue(listOfEnumsContent.contains("VALUE10") && listOfEnumsContent.contains("VALUE11"),
"Wrapper message should contain enum values");
output.deleteOnExit();
}
@Test(description = "Validate that enums in arrays remain inline when extractEnumsToSeparateFiles is NOT enabled")
public void testEnumsInArraysWithoutExtraction() throws IOException {
// set line break to \n across all platforms
System.setProperty("line.separator", "\n");
File output = Files.createTempDirectory("test").toFile();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("protobuf-schema")
.setInputSpec("src/test/resources/3_0/protobuf-schema/extracted_enum.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
// Note: EXTRACT_ENUMS_TO_SEPARATE_FILES is NOT enabled
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
// Check that the model file was generated
TestUtils.ensureContainsFile(files, output, "models/model_with_enums.proto");
Path modelPath = Paths.get(output + "/models/model_with_enums.proto");
String modelContent = new String(Files.readAllBytes(modelPath), StandardCharsets.UTF_8)
.replace("\r\n", "\n").replace("\r", "\n");
// Without extraction: Arrays of enums should NOT use .Enum suffix
// Instead, they should use the type directly or inline definition
Assert.assertFalse(modelContent.contains(".Enum"),
"Without extraction, enums should NOT use .Enum suffix");
// Extracted inline enum files should NOT exist
Assert.assertFalse(Files.exists(Paths.get(output + "/models/model_with_enums_list_of_enums.proto")),
"Without extraction, inline enum array files should NOT be generated");
output.deleteOnExit();
}
}

View File

@@ -0,0 +1,62 @@
package org.openapitools.codegen.rust;
import org.openapitools.codegen.DefaultGenerator;
import org.openapitools.codegen.TestUtils;
import org.openapitools.codegen.config.CodegenConfigurator;
import org.testng.annotations.Test;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
/**
* Tests for RustServerCodegen.
*/
public class RustServerCodegenTest {
/**
* Test that integer parameters with minimum/maximum constraints are assigned appropriate Rust types.
* This tests that integer parameter type fitting logic is applied to CodegenParameter objects.
*/
@Test
public void testIntegerParameterTypeFitting() throws IOException {
Path target = Files.createTempDirectory("test");
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("rust-server")
.setInputSpec("src/test/resources/3_0/rust-server/integer-params.yaml")
.setSkipOverwrite(false)
.setOutputDir(target.toAbsolutePath().toString().replace("\\", "/"));
List<File> files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate();
files.forEach(File::deleteOnExit);
Path libPath = Path.of(target.toString(), "/src/lib.rs");
TestUtils.assertFileExists(libPath);
// Verify that parameters with known min/max ranges get appropriate types
// age: 0-150 should fit in u8
TestUtils.assertFileContains(libPath, "age: u8");
// temperature: -50 to 50 should fit in i8
TestUtils.assertFileContains(libPath, "temperature: i8");
// count: 0-65535 should fit in u16
TestUtils.assertFileContains(libPath, "count: u16");
// offset: -32768 to 32767 should fit in i16
TestUtils.assertFileContains(libPath, "offset: i16");
// large_unsigned: 0-4294967295 should be u32
TestUtils.assertFileContains(libPath, "large_unsigned: u32");
// Verify integer with int32 format and minimum >= 0 becomes u32
TestUtils.assertFileContains(libPath, "positive_int32: u32");
// Verify integer with int64 format and minimum >= 0 becomes u64
TestUtils.assertFileContains(libPath, "positive_int64: u64");
// Clean up
target.toFile().deleteOnExit();
}
}

View File

@@ -48,6 +48,8 @@ components:
properties:
name:
type: string
characteristics:
$ref: '#/components/schemas/Characteristics'
Reptile:
allOf:
- $ref: '#/components/schemas/Pet'
@@ -78,7 +80,7 @@ components:
- $ref: '#/components/schemas/Lizard'
discriminator:
propertyName: petType
# per https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#discriminatorObject
# per https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#discriminator-object
# this discriminator must be included to use it as a hint to pick a schema
MyPetsNoDisc:
oneOf:
@@ -101,3 +103,8 @@ components:
C:
allOf:
- $ref: '#/components/schemas/B'
Characteristics:
type: object
properties:
canHunt:
type: boolean

View File

@@ -0,0 +1,58 @@
openapi: 3.0.3
info:
title: OAI Specification example for Polymorphism
version: 1.0.0
paths:
/status:
get:
responses:
'201':
description: desc
components:
schemas:
Animal:
type: object
required:
- petType
properties:
petType:
type: string
discriminator:
propertyName: petType
mapping:
dog: '#/components/schemas/Dog'
cat: '#/components/schemas/Cat'
Feline:
allOf:
- $ref: '#/components/schemas/Animal'
- type: object
properties:
name:
type: string
furColor:
type: string
Cat:
allOf:
- $ref: '#/components/schemas/Feline'
- type: object
properties:
isIndoor:
type: boolean
careDetails:
$ref: '#/components/schemas/CareDetails'
Dog:
allOf:
- $ref: '#/components/schemas/Animal'
- type: object
properties:
bark:
type: string
CareDetails:
type: object
properties:
veterinarian:
type: string
lastVetVisit:
type: string
format: date

View File

@@ -0,0 +1,52 @@
openapi: 3.0.0
info:
title: Test Escaping in Examples
version: 1.0.0
paths:
/test:
get:
operationId: testEscaping
tags:
- test
parameters:
- name: stringWithQuotes
in: query
required: true
schema:
type: string
example: 'John "Johnny" Doe'
- name: stringWithBackslash
in: query
required: true
schema:
type: string
example: 'C:\path\to\file'
- name: emailWithQuotes
in: query
required: true
schema:
type: string
format: email
example: 'test"user@example.com'
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/TestResponse'
components:
schemas:
TestResponse:
type: object
properties:
name:
type: string
example: 'Name with "quotes" inside'
path:
type: string
example: 'C:\Windows\System32'
email:
type: string
format: email
example: 'user"name@example.com'

View File

@@ -41,8 +41,19 @@ components:
format: uuid
optional_property:
type: number
stringSet:
type: array
items:
type: string
uniqueItems: true
stringArray:
type: array
items:
type: string
required:
- id
- string_set
- string_array
discriminator:
propertyName: discriminator
mapping:

View File

@@ -0,0 +1,31 @@
/*
OAI Specification example for Polymorphism
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 1.0.0
Generated by OpenAPI Generator: https://openapi-generator.tech
*/
syntax = "proto3";
package openapitools;
import public "models/care_details.proto";
message Animal {
string pet_type = 482112090;
string name = 3373707;
string fur_color = 478695002;
bool is_indoor = 183319801;
CareDetails care_details = 176721135;
string bark = 3016376;
}

View File

@@ -0,0 +1,77 @@
openapi: 3.0.0
info:
title: Enum extraction test
version: '2.0'
paths: {}
components:
schemas:
SeparatedEnum:
type: string
enum:
- VALUE1
- VALUE2
ModelWithEnums:
type: object
properties:
referenceEnumProperty:
$ref: "#/components/schemas/SeparatedEnum"
inlineEnumProperty:
type: string
enum:
- VALUE2
- VALUE3
- VALUE4
listOfEnums:
type: array
items:
type: string
enum:
- VALUE10
- VALUE11
AllOfModelWithEnums:
allOf:
- $ref: "#/components/schemas/ModelWithEnums"
- type: object
properties:
anotherInlineEnumProperty:
type: string
enum:
- VALUE5
- VALUE6
listOfReferencedEnums:
type: array
items:
$ref: '#/components/schemas/SeparatedEnum'
DiscriminatedModel:
type: object
properties:
commonProperty:
type: string
modelType:
type: string
discriminator:
propertyName: modelType
mapping:
typeA: "#/components/schemas/ModelTypeAWithInlineEnum"
typeB: "#/components/schemas/ModelTypeBWithInlineEnum"
ModelTypeAWithInlineEnum:
allOf:
- $ref: "#/components/schemas/DiscriminatedModel"
- type: object
properties:
specificPropertyA:
type: string
inlineEnumProperty:
type: string
enum:
- VALUE7
- VALUE8
ModelTypeBWithInlineEnum:
allOf:
- $ref: "#/components/schemas/DiscriminatedModel"
- type: object
properties:
specificPropertyB:
type: string
referenceEnumPropertyB:
$ref: "#/components/schemas/SeparatedEnum"

View File

@@ -0,0 +1,89 @@
openapi: 3.0.0
info:
title: Model Import Test
version: 1.0.0
paths: {}
components:
schemas:
A:
type: object
description: Base model A that will be referenced multiple times
properties:
id:
type: string
value:
type: string
required:
- id
SubModel:
type: object
description: SubModel that uses model A
allOf:
- $ref: '#/components/schemas/ExtensibleModel'
- type: object
properties:
subField:
type: string
aReference:
$ref: '#/components/schemas/A'
required:
- subField
Model:
type: object
description: Main model that uses A directly and via SubModel
properties:
name:
type: string
directA:
$ref: '#/components/schemas/A'
nestedSubModel:
$ref: '#/components/schemas/SubModel'
required:
- name
ExtensibleModel:
type: object
description: Extensible model with discriminator that uses model A
discriminator:
propertyName: type
mapping:
child1: '#/components/schemas/ChildModel_1'
child2: '#/components/schemas/ChildModel_2'
properties:
type:
type: string
extensibleA:
$ref: '#/components/schemas/A'
required:
- type
ChildModel_1:
allOf:
- $ref: '#/components/schemas/ExtensibleModel'
- type: object
properties:
childSpecificField:
type: string
childA:
$ref: '#/components/schemas/A'
ChildModel_2:
allOf:
- $ref: '#/components/schemas/SubExtensibleModel'
- type: object
properties:
anotherChildSpecificField:
type: integer
directA:
$ref: '#/components/schemas/A'
SubExtensibleModel:
allOf:
- $ref: '#/components/schemas/ExtensibleModel'
- type: object
properties:
aSubExtensibleField:
type: boolean
subDirectA:
$ref: '#/components/schemas/A'

View File

@@ -12,14 +12,20 @@ syntax = "proto3";
package openapitools;
import public "models/characteristics.proto";
message Pet {
string pet_type = 482112090;
string name = 3373707;
Characteristics characteristics = 455429578;
string bark = 3016376;
bool loves_rocks = 465093427;
bool has_legs = 140596906;
}

View File

@@ -0,0 +1,82 @@
# Test that integer parameters are generated into the right
# primitives in Rust code.
openapi: 3.1.1
info:
title: Integer Parameter Type Fitting Test
description: Test spec to verify that integer parameters with minimum/maximum constraints get appropriate Rust types
version: 1.0.0
servers:
- url: http://localhost:8080
paths:
/test/integers:
get:
operationId: testIntegerParameters
summary: Test integer parameter type fitting
parameters:
# age: 0-150 should fit in u8 (unsigned, 8-bit)
- name: age
in: query
required: true
schema:
type: integer
minimum: 0
maximum: 150
# temperature: -50 to 50 should fit in i8 (signed, 8-bit)
- name: temperature
in: query
required: true
schema:
type: integer
minimum: -50
maximum: 50
# count: 0-65535 should fit in u16 (unsigned, 16-bit)
- name: count
in: query
required: true
schema:
type: integer
minimum: 0
maximum: 65535
# offset: -32768 to 32767 should fit in i16 (signed, 16-bit)
- name: offset
in: query
required: true
schema:
type: integer
minimum: -32768
maximum: 32767
# large_unsigned: 0-4294967295 should be u32
- name: large_unsigned
in: query
required: true
schema:
type: integer
minimum: 0
maximum: 4294967295
# positive_int32: format int32 with min >= 0 should become u32
- name: positive_int32
in: query
required: true
schema:
type: integer
format: int32
minimum: 0
# positive_int64: format int64 with min >= 0 should become u64
- name: positive_int64
in: query
required: true
schema:
type: integer
format: int64
minimum: 0
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
success:
type: boolean

View File

@@ -0,0 +1,24 @@
openapi: 3.0.4
info:
title: "Different response schemas including an empty one"
version: "1.0.0"
paths:
/example:
get:
operationId: exampleGet
responses:
200:
description: "A successful response with data"
content:
application/json:
schema:
type: integer
400:
description: "A bad request with a message"
content:
application/json:
schema:
type: string
500:
description: "An internal server error with no content"
content: { }

View File

@@ -96,6 +96,7 @@ public class Bird {
this.color = color;
}
@Override
public boolean equals(Object o) {
if (this == o) {

View File

@@ -96,6 +96,7 @@ public class Category {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) {

View File

@@ -132,6 +132,7 @@ public class DataQuery extends Query {
this.date = date;
}
@Override
public DataQuery id(@javax.annotation.Nullable Long id) {
this.setId(id);

View File

@@ -409,6 +409,7 @@ public class DefaultValue {
this.stringNullable = JsonNullable.<String>of(stringNullable);
}
@Override
public boolean equals(Object o) {
if (this == o) {

View File

@@ -129,6 +129,7 @@ public class NumberPropertiesOnly {
this._double = _double;
}
@Override
public boolean equals(Object o) {
if (this == o) {

View File

@@ -274,6 +274,7 @@ public class Pet {
this.status = status;
}
@Override
public boolean equals(Object o) {
if (this == o) {

View File

@@ -144,6 +144,7 @@ public class Query {
this.outcomes = outcomes;
}
@Override
public boolean equals(Object o) {
if (this == o) {

View File

@@ -96,6 +96,7 @@ public class Tag {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) {

View File

@@ -67,6 +67,7 @@ public class TestFormObjectMultipartRequestMarker {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) {

View File

@@ -157,6 +157,7 @@ public class TestQueryStyleDeepObjectExplodeTrueObjectAllOfQueryObjectParameter
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) {

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