ProbablyClem / utoipauto

Rust Macros to automate the addition of Paths/Schemas to Utoipa crate, simulating Reflection during the compilation phase
Apache License 2.0
108 stars 10 forks source link

Working with external types #4

Closed squadgazzz closed 7 months ago

squadgazzz commented 8 months ago

Let's consider the following example:

#[derive(ToSchema, Debug, Serialize)]
pub struct Solution {
    id: u64,
    #[serde_as(as = "HashMap<_, serialize::U256>")]
    prices: HashMap<String, ethereum_types::U256>,
}

Where ethereum_types::U256 is external type and serialize::U256 is a wrapper which implements the following:

#[derive(Debug)]
pub struct U256;

impl<'de> DeserializeAs<'de, ethereum_types::U256> for U256 {
  ...
}

impl SerializeAs<ethereum_types::U256> for U256 {
  ...
}

impl<'s> utoipa::ToSchema<'s> for U256 {
    fn schema() -> (&'s str, RefOr<Schema>) {
        (
            "string",
            ObjectBuilder::new()
                .schema_type(SchemaType::String)
                .into()
        )
    }
}

Is there a way to use utoipauto for this scenario? It looks like I need to explicitly declare which ToSchema to use for the type like it's done for serde: #[serde_as(as = "HashMap<_, serialize::U256>")]. Is there a workaround?

ProbablyClem commented 8 months ago

Hello,

Right now, utoipauto only supports struct that derives ToSchema, because we don't have access to the Rust type system in the macro.

I think we may add an optional macro annotation to explicitly say that a struct impl ToSchema manually. Or we could just search for ToSchema impl block in the whole source code.

As a workaround, you can add the struct to utoipa manually. Utoipauto supports having both automatic and manual imports.

#[utoipauto] // auto imports
#[derive(OpenApi)]
#[openapi(
    components(
        schemas(TestDTO) //manual imports
    ),
)]

pub struct ApiDoc;
ProbablyClem commented 7 months ago

Hey, it's been fixed in 1.7 thanks to this PR