juhaku / utoipa

Simple, Fast, Code first and Compile time generated OpenAPI documentation for Rust
Apache License 2.0
2.49k stars 197 forks source link

Name clash for `Object` #833

Open marcustut opened 10 months ago

marcustut commented 10 months ago

I have a struct Object

    #[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct Object {
        #[cfg_attr(feature = "openapi", schema(format = Uuid))]
        pub id: Uuid,
        #[cfg_attr(feature = "openapi", schema(format = DateTime))]
        pub updated_at: DateTime<Utc>,
        #[cfg_attr(feature = "openapi", schema(format = DateTime))]
        pub created_at: DateTime<Utc>,
    }

and in my Axum routes I use it like so

    #[utoipa::path(
        post,
        path = "/storage/buckets/{bucket_id}/objects",
        operation_id = "Create a new object on the bucket",
        tag = "storage",
        request_body(content = CreateBucketObjectRequest, content_type = "multipart/form-data"),
        responses(
            (status = 200, description = "Returns a newly created object", body = Object),
            (status = 500, description = "Internal server error", body = String)
        ),
        security(
            ("Bearer" = [])
        )
    )]
    pub async fn create_object(
        Auth0UserClaims(claims): Auth0UserClaims,
        State(app): State<AppState>,
        Path(bucket_id): Path<Uuid>,
        mut multipart: Multipart, // NOTE: This must be the last extractor because it consumes the request body
    ) -> Result<impl IntoResponse, AnyhowError> {
        ...
    }

The generated OpenAPI Specs then becomes

        "responses": {
          "200": {
            "description": "Returns a newly created object",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
        },

but the correct output should be "$ref": "#/components/schemas/Object" instead of "type": "object"

Note

If I rename the struct from Object to StorageObject then it behaves normally again where it outputs "$ref": "#/components/schemas/StorageObject".

juhaku commented 2 months ago

@marcustut That is by desing. Excerpt from the docs:

value_type = ... Can be used to override default type derived from type of the field used in OpenAPI spec. This is useful in cases where the default type does not correspond to the actual type e.g. when any third-party types are used which are not ToSchemas nor primitive types. The value can be any Rust type what normally could be used to serialize to JSON or either virtual type Object or Value, or an alias defined using #[aliases(..)]. Object will be rendered as generic OpenAPI object (type: object). Value will be rendered as any OpenAPI value (i.e. no type restriction).

Though perhaps in future this can be made configurable. But as of now there are no such plans.