Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using generic schema as type for another generic schema #703

Closed
nik-here opened this issue Jul 23, 2023 · 4 comments · Fixed by #1034
Closed

Using generic schema as type for another generic schema #703

nik-here opened this issue Jul 23, 2023 · 4 comments · Fixed by #1034
Labels
enhancement New feature or request Generics - Hard Stuff concerning generics implementation

Comments

@nik-here
Copy link

Description

Hi, as mentioned in the title, I want to use a generic schema as a type for another generic schema.

The problem

All aliases for GenericStructA<T> prompt error messages.

What do I expect?

GenericStructAString, GenericStructAInt, and GenericStructANotGenericStruct will create references to GenericStructBString, GenericStructBInt, and GenericStructBNotGenericStruct. Or even better I don't have to create those aliases for GenericStructB<T> and they will be created automatically by creating those aliases for GenericStructA<T>

// main.rs
use actix_web::{middleware::Logger, App, HttpServer, Result};
use std::{error::Error, net::Ipv4Addr};
use utoipa::{OpenApi, ToSchema};
use utoipa_swagger_ui::SwaggerUi;

#[derive(ToSchema)]
#[aliases(GenericStructAString = GenericStructA<String>, GenericStructAInt = GenericStructA<i32>, GenericStructANotGenericStruct = GenericStructA<NotGenericStruct>)]
pub struct GenericStructA<T> {
    pub field_a: String,
    pub field_b: i32,
    pub generic_struct_b: GenericStructB<T>,
}

#[derive(ToSchema)]
#[aliases(GenericStructBString = GenericStructB<String>, GenericStructBInt = GenericStructB<i32>, GenericStructBNotGenericStruct = GenericStructB<NotGenericStruct>)]
pub struct GenericStructB<T> {
    pub field_c: bool,
    pub field_d: f32,
    pub generic_field: T,
}

#[derive(ToSchema)]
pub struct NotGenericStruct {
    pub field_e: String,
    pub field_f: i32,
}

#[actix_web::main]
async fn main() -> Result<(), impl Error> {
    #[derive(OpenApi)]
    #[openapi(
        paths(),
        components(schemas(
            NotGenericStruct,
            GenericStructBString,
            GenericStructBInt,
            GenericStructBNotGenericStruct,
            GenericStructAString,
            GenericStructAInt,
            GenericStructANotGenericStruct
        ))
    )]
    struct ApiDoc;

    let openapi = ApiDoc::openapi();

    HttpServer::new(move || {
        App::new().wrap(Logger::default()).service(
            SwaggerUi::new("/swagger-ui/{_:.*}").url("/api-docs/openapi.json", openapi.clone()),
        )
    })
    .bind((Ipv4Addr::UNSPECIFIED, 8080))?
    .run()
    .await
}
# Cargo.toml
[package]
name = "testing"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
actix-web = "4.3.1"
utoipa = { version = "3", features = ["actix_extras"] }
utoipa-swagger-ui = { version = "3", features = ["actix-web"] }

image

@juhaku
Copy link
Owner

juhaku commented Aug 22, 2023

This is probably something that needs a little or perhaps even more investigation and exploration. I don't have the time to get to this right now, but perhaps this could be addressed in future.

The generics are quite troublesome because of the design of the utoipa library. Since the utoipa is compile-time the types need to be know before hand at the declaration level and not when they are being used at runtime. This is the reason why aliases are used as a first place to allow generic types in some form but the current implementation does not take into account existing aliases when generating spec for a generic type that already has aliases.

A word of caution. It might be possible to support this behavior but same goes other way as well. This functionality might be difficult or near impossible to implement.

@juhaku juhaku added the prio 2 / future investigation Investigate in future the possibility of implementation label Aug 22, 2023
@juhaku juhaku added Generics - Hard Stuff concerning generics implementation enhancement New feature or request and removed prio 2 / future investigation Investigate in future the possibility of implementation labels Sep 4, 2024
@juhaku
Copy link
Owner

juhaku commented Sep 10, 2024

There is now new implementation for generics coming up in #1034 which should solve the issue with aliases approach.

@nik-here
Copy link
Author

@juhaku Thank you very much for solving the problems with generics and of course for your time for doing this. ☺️

@juhaku
Copy link
Owner

juhaku commented Sep 10, 2024

Thank you for giving inspiration for the solution. It is somewhat based on your example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Generics - Hard Stuff concerning generics implementation
Projects
Status: Released
Development

Successfully merging a pull request may close this issue.

2 participants