OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.42k stars 6.48k forks source link

[BUG][RUST] oneOf with value and array results in invalid code #18984

Open jath03 opened 3 months ago

jath03 commented 3 months ago

Bug Report Checklist

Description

Basically, using a oneof in rust generates an enum. When actually using that enum to make a request, there is an error because the enum cannot be converted to a string because it doesn't implement the display trait.

To fix this, there are two options:

  1. Implement the display trait for the enum so that it converts itself into a string correctly (not ideal because you'd have to deal with url encoding when you implement the trait).
  2. Handle each enum variant when you are building the request (which is what I implemented - see below)
Full Error from output error[E0599]: the method `to_string` exists for reference `&GetSystemWaypointsTraitsParameter`, but its trait bounds were not satisfied --> src/apis/systems_api.rs:256:89 | 256 | local_var_req_builder = local_var_req_builder.query(&[("traits", &local_var_str.to_string())]); | ^^^^^^^^^ method cannot be called on `&GetSystemWaypointsTraitsParameter` due to unsatisfied trait bounds | ::: src/models/get_system_waypoints_traits_parameter.rs:16:1 | 16 | pub enum GetSystemWaypointsTraitsParameter { | ------------------------------------------ doesn't satisfy `GetSystemWaypointsTraitsParameter: ToString` or `_: Display` | = note: the following trait bounds were not satisfied: `GetSystemWaypointsTraitsParameter: std::fmt::Display` which is required by `GetSystemWaypointsTraitsParameter: ToString` `&GetSystemWaypointsTraitsParameter: std::fmt::Display` which is required by `&GetSystemWaypointsTraitsParameter: ToString` note: the trait `std::fmt::Display` must be implemented --> /home/jack/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/mod.rs:705:1 | 705 | pub trait Display { | ^^^^^^^^^^^^^^^^^ = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `to_string`, perhaps you need to implement it: candidate #1: `ToString` For more information about this error, try `rustc --explain E0599`. error: could not compile `openapi` (lib) due to 1 previous error
openapi-generator version

7.6.0 also tested with latest snapshot

OpenAPI declaration file content or url

https://raw.githubusercontent.com/SpaceTradersAPI/api-docs/main/reference/SpaceTraders.json Specific offending portion: https://github.com/SpaceTradersAPI/api-docs/blob/3ff410cbfe2ab9f05b73a7d1d92cca0593480018/reference/SpaceTraders.json#L513C11-L529C14

Generation Details

This is the command I was using

openapi-generator-cli generate -i spacetraders-api-docs-spacedust-patch/reference/SpaceTraders.json -g rust -o client-dist --additional-properties=packageName=spacedust,supportAsync=true,supportMiddleware=true
Steps to reproduce
git clone https://github.com/SpaceTradersAPI/api-docs
openapi-generator-cli generate -i api-docs/reference/SpaceTraders.json -g rust -o client-dist
cd client-dist
cargo check
Related issues/PRs

Seems to be somewhat related to this previously fixed issue: https://github.com/OpenAPITools/openapi-generator/issues/17896 Searching the issue list for rust oneof comes up with a few that seems to be somewhat similar but not the same: https://github.com/OpenAPITools/openapi-generator/issues/18527 https://github.com/OpenAPITools/openapi-generator/issues/17210 https://github.com/OpenAPITools/openapi-generator/issues/13257 https://github.com/OpenAPITools/openapi-generator/issues/9497 https://github.com/OpenAPITools/openapi-generator/issues/7802 https://github.com/OpenAPITools/openapi-generator/issues/3297

Suggest a fix

This is what I did to fix the generated code, but I don't know how I would fix the generator.

$ diff client-dist4/src/apis/systems_api.rs client-dist2/src/apis/systems_api.rs 
255,256c255,267
<     if let Some(ref local_var_str) = traits {
<         local_var_req_builder = local_var_req_builder.query(&[("traits", &local_var_str.to_string())]);
---
>     if let Some(ref local_var_enum) = traits {
>         if let models::GetSystemWaypointsTraitsParameter::Array(local_str_array) = local_var_enum {
>             for local_var_str in local_str_array {
>                 local_var_req_builder =
>                     local_var_req_builder.query(&[("traits", &local_var_str.to_string())]);
>             }
>         } else if let models::GetSystemWaypointsTraitsParameter::WaypointTraitSymbol(
>             local_var_str,
>         ) = local_var_enum
>         {
>             local_var_req_builder =
>                 local_var_req_builder.query(&[("traits", &local_var_str.to_string())]);
>         }

This is just something that works. I'm not necessarily recommending this because I don't know the conventions for generated code or what you have available in the generator.