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

Types with same name overrides schemas in components #1

Open
Flowneee opened this issue Feb 15, 2023 · 2 comments
Open

Types with same name overrides schemas in components #1

Flowneee opened this issue Feb 15, 2023 · 2 comments
Labels
bug Something isn't working

Comments

@Flowneee
Copy link
Owner

Flowneee commented Feb 15, 2023

If there is 2 or more types with same name, they will override each other, when schema generated. For example

handler1.rs

#[derive(JsonSchema)]
struct Request {
    name: String
}

handler2.rs

#[derive(JsonSchema)]
struct Request {
    id: u64
}

will create only one definition in #/components/schema, and handlers from both files wil reference same schema.

First potenial fix - enable inlining in https://docs.rs/schemars/latest/schemars/gen/struct.SchemaSettings.html#structfield.inline_subschemas, which will solve most problems (probably everything sxcept recursive types).

@Flowneee Flowneee added the bug Something isn't working label Feb 15, 2023
@Flowneee
Copy link
Owner Author

Proper solution could be adding some attribute to schemars macro JsonSchema, which will make type non-referenceable, like

#[derive(JsonSchema)]
#[schemars(referenceable = false)]
struct Request { ... }

@Flowneee
Copy link
Owner Author

I thought about this (for a year+, lol), and I think proper solution is to move from using schemars generator as container for all schemas to custom implementation.

Approximate design: current Components removed and replaced with OpenApiBuilder in all signatures. OpenApiBuilder have following definition

struct OpenApiBuilder {
    spec: OpenApi, // spec from okapi
    conflict_schemas: HashSet<String>,
}

where spec's components.schemas will act as storage for all known referenceable schemas and conflict_schemas will include type names, where different types had same name.

Builder will provide single method .schema_for<T: JsonSchema>() -> RefOr<SchemaObject> with this logic:

  1. If T is not referenceable, then return it as-is, otherwise proceed to next steps;
  2. Generate root schema with schemars generator
  3. For each schema in generated root schema:
    • If schema name in conflict_schemas, replace all references to new schema in generated schemas with actual definition;
    • If schema name is not in spec.content.schemas, put it there
    • If schema name is in spec.content.schemas and content is equal, skip this schema
    • If schema name is in spec.content.schemas and content is different:
      1. put schema name in conflict_schemas;
      2. remove existing schema from spec and replace all references to it in spec with actual definition;
      3. replace all references to new schema in generated schemas with actual definition;
    • If current schema is for requested type, store it (ore reference to it) in additional variable.

Only problem left is if you use same name for different types like this

struct Request {
    a: crate_a::MyField,
    b: crate_b::MyField // actually different from crate_a::MyField
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant