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

Wrapper classes for primitive types #114

Open
Gama11 opened this issue Mar 4, 2022 · 1 comment
Open

Wrapper classes for primitive types #114

Gama11 opened this issue Mar 4, 2022 · 1 comment

Comments

@Gama11
Copy link
Contributor

Gama11 commented Mar 4, 2022

In our codebase, we have a lot of single-argument data classes to wrap raw strings / integers / UUIDs / etc. This improves type safety (mixing up different things that happen to have the same type now causes a compiler error) and readability. With openapi-generator, we were able to get the generated models to use these (hand-written) wrappers by using their type and import mapping features.

However, I'm thinking that ideally, the wrappers would be generated as well. Basically, the idea would be that if there is an explicit named schema, it is always generated. Right now, the following simply "inlines" the AccountToken schema, so Account has a token: UUID argument:

openapi: 3.0.0
components:
  schemas:
    Account:
      type: object
      required:
        - token
      properties:
        token:
          $ref: '#/components/schemas/AccountToken'
    AccountToken:
      type: string
      format: uuid

With a potential new CLI flag, it could instead generate something like this instead:

data class Account(
  @param:JsonProperty("token")
  @get:JsonProperty("token")
  @get:NotNull
  val token: AccountToken
)

data class AccountToken(
  @get:JsonValue
  @get:NotNull
  val value: UUID
)

The @get:JsonValue ensures that Jackson (de)serialization works as expected, i.e. treating it as a JSON string rather than a JSON object. In the future, it might even make sense for the wrappers to be @JvmInline value classes, right now it seems Jackson doesn't like those.


The other complication here (and technically a separate problem) is that we have a lot of these wrapper schemas in shared spec files (think $ref: 'shared/tokens.yml#/components/schemas/AccountToken') used by many different APIs, and we generate each API into a separate Gradle module. By default that would lead to a lot of duplicated types being generated that are not compatible with each other. To avoid that we would need some mechanism to say "if the schema comes from a separate yml file, don't generate a type and instead assume it can be found in this package" (so perhaps a map from .yml file path to package paths).


These two things seem to be the biggest remaining blockers for us to be able to switch from openapi-generator to fabrikt.

Would you be interested in supporting these use cases in fabrikt? If desired I could have a stab at implementing this in the form of a pull request sometime. I'm open to discussing alternative ideas as well. :)

@cjbooms
Copy link
Owner

cjbooms commented Mar 7, 2022

Open to any PRs you might want to contribute to achieve this. But I won't be in a position to help much with the implementation aside from reviewing any PRs you create.

The type mapping functionality might be an easier first thing to try and replicate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants