openapi-generator
openapi-generator copied to clipboard
[BUG][RUST] oneOf with multiple arrays produces invalid rust code
Bug Report Checklist
- [x] Have you provided a full/minimal spec to reproduce the issue?
- [x] Have you validated the input using an OpenAPI validator (example)?
- [x] Have you tested with the latest master to confirm the issue still exists?
- [x] Have you searched for related issues/PRs?
- [x] What's the actual output vs expected output?
- [ ] [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
If there is no title
, the rust generator tries to derive a meaningful name from the type (see https://github.com/OpenAPITools/openapi-generator/issues/17896). However, this fails in some cases, for example if there is a oneOf
with multiple arrays inside.
The OpenAPI spec below produces the following enum:
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Option1OrOption2Options {
Array(Vec<String>),
Array(Vec<i32>),
}
This cannot be compiled, the error message is error[E0428]: the name 'Array' is defined multiple times
. I would expect that all code generated from a valid OpenAPI spec generates compilable rust code.
openapi-generator version
I tested with version 06ed7c82056aace4651d65ec56b68e4520739b53 (the current main).
OpenAPI declaration file content or url
openapi: 3.0.0
info:
title: oneOf with arrays
description: Ensure different names for kinds in enum when using oneOf with arrays.
version: 1.0.0
paths: {}
components:
schemas:
Option1OrOption2:
type: object
properties:
Options:
oneOf:
- type: array
items:
type: string
- type: array
items:
type: integer
Steps to reproduce
I'll provide the steps to create a failing test using the valid OpenAPI spec above.
-
Add the snippet above to the test resources (e.g.
modules/openapi-generator/src/test/resources/3_0/rust/oneof-with-arrays.yaml
). -
Create a config for the test (e.g.
bin/configs/rust-reqwest-oneOf-with-arrays.yaml
):generatorName: rust outputDir: samples/client/others/rust/reqwest/oneOf-with-arrays library: reqwest inputSpec: modules/openapi-generator/src/test/resources/3_0/rust/oneof-with-arrays.yaml templateDir: modules/openapi-generator/src/main/resources/rust additionalProperties: supportAsync: false packageName: oneof-with-arrays-reqwest
-
Generate the rust samples with
./bin/generate-samples.sh ./bin/configs/rust-*
. -
Execute the tests with
mvn integration-test -f samples/client/others/rust/pom.xml
.
Related issues/PRs
- Not long ago, the rust type was directly used as the enum kind, see https://github.com/OpenAPITools/openapi-generator/issues/17896.
- This was changed in https://github.com/OpenAPITools/openapi-generator/pull/17915 solving https://github.com/OpenAPITools/openapi-generator/issues/17896.
- https://github.com/OpenAPITools/openapi-generator/issues/17210 is a follow up issue but it's different from the issue I am opening here.
Suggest a fix
I'm new to rust and to openapi-generator, so I am no help here, sorry.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Option1OrOption2Options {
Array(Vec<String>),
Array(Vec<i32>),
}
ideally what's the correct/expected code look like?
There is probably not a really nice way as there is just not much information. Maybe one could enumerate the enum fields:
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Option1OrOption2Options {
Array1(Vec<String>),
Array2(Vec<i32>),
}
Those are not helpful variable names but at least it could be compiled. Maybe the generators for the other languages in this project have a nicer way to solve this?
what about the following instead?
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Option1OrOption2Options {
ArrayVecString(Vec<String>),
ArrayVeci32(Vec<i32>),
}
Theoretically, the following is also a valid OpenAPI spec:
openapi: 3.0.0
info:
title: oneOf with arrays
description: Ensure different names for kinds in enum when using oneOf with arrays.
version: 1.0.0
paths: {}
components:
schemas:
Option1OrOption2:
type: object
properties:
Options:
oneOf:
- type: array
items:
type: string
- type: array
items:
type: string
With your proposition, this would result in a name clash again. However, depending on whether you want to support all edge cases of OpenAPI, that might be okay because the semantics of the spec above are not clear (why even have a oneOf
if both alternatives are exactly the same?).
I found something similar to this today. We have something like this:
openapi: 3.0.0
info:
title: oneOf with arrays
description: Ensure different names for kinds in enum when using oneOf with arrays.
version: 1.0.0
paths: {}
components:
schemas:
Option1OrOption2:
type: object
properties:
Options:
oneOf:
- type: string
filter: '^\d{4}$'
- type: string
maxLength: 0
This should also generate distinct types.
This also has another problem as this will currently create a String
enum member which is already defined for the native Rust's String
type.
I would also think that just generating distinct names would be a good idea. Then you can map this name with --type-mappings
.
Any further plans on tackling this?
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(untagged)] pub enum Option1OrOption2Options { ArrayVecString(Vec<String>), ArrayVeci32(Vec
), }
Your suggestion is the imo the most idiomatic solution. If someone could point me in the direction of where the name
variable is constructed in the java source, I'll get it done.
@wing328