-
-
Notifications
You must be signed in to change notification settings - Fork 7.4k
Description
Bug Report Checklist
- Have you provided a full/minimal spec to reproduce the issue?
- Have you validated the input using an OpenAPI validator (example)? // Dead URL
- Have you tested with the latest master to confirm the issue still exists?
- Have you searched for related issues/PRs?
- What's the actual output vs expected output?
- [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
The structure generated by models using oneOf cannot be easily or efficiently converted to the specific structure type.
Using the provided declaration, with the current implementation of oneOf and anyOf handling, generates a Message struct with a private field of the RawValue type, with 2 additional structures named Hello and Goodbye that have usable fields and traits. The generated endpoint Default/foo gets Message provided as one of its arguments, but this type is mostly useless. There is no enumeration or information available within the structure to facilitate obtaining the adequate model programmatically, with no guarantee that further modifications to the model (ones that add or remove fields to the list of variants) will have explicit handling within the user code. The only way to currently use the Message structure semi-reasonably is done by attempting to deserialize Hello and Goodbye from Message and seeing which one does not fail, or deserializing Value from Message, manually checking the tagged field, and generating the adequate type from there. Both of these options complicate the error handling and the use of the values, as they have separate types and cannot be assigned to the same variable.
openapi-generator version
7.10.0-SNAPSHOT
OpenAPI declaration file content or url
https://gist.github.com/Victoria-Casasampere-BeeTheData/e6c856d1dad01e64e21fa0f7701759d4
Generation Details
openapi-generator-cli generate -g rust-axum -o outoutrs -i base.yaml
Steps to reproduce
Use the rust-axum generator with the provided declaration or any declaration using oneOf as a model content.
Related issues/PRs
Possibly #15, but most likely none.
Suggest a fix
I would replace the current implementation with one that uses enum serde representations instead.
Untagged would be used when discriminator is not defined:
#[derive(Serialize, Deserialize)]
#[serde(untagged)]
pub enum Message {
Hello(Hello),
Goodbye(Goodbye),
}
#[derive(Serialize, Deserialize)]
pub struct Hello {
pub op: String,
pub welcome_message: String,
}
#[derive(Serialize, Deserialize)]
pub struct Goodbye {
pub op: String,
pub goodbye_message: String,
}Internally tagged enums are used when discriminator.propertyName is defined:
#[derive(Serialize, Deserialize)]
#[serde(tag = "op")]
pub enum Message {
// ` mapping`s would lead to aliases
#[serde(alias = "Hello", alias = "Greetings")]
Hello(Hello),
#[serde(alias = "Goodbye")]
Goodbye(Goodbye),
}
// Note that tagged enums do not deserialize the tag to a field. If it were to be necessary, a possible
// solution to this would be to generate a method with the tag field name that returns the value.
// eg. `fn op() -> &'static str { "Hello" }`
#[derive(Serialize, Deserialize)]
pub struct Hello {
pub welcome_message: String,
}
#[derive(Serialize, Deserialize)]
pub struct Goodbye {
pub goodbye_message: String,
}This solution could also be reused to support inline enums in the future, and oneOf enum mappings from OpenAPI 3.1 (see this stack overflow)