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

Open API 3 Specs Generation #5

Open
dacloutier opened this issue Oct 5, 2023 · 2 comments
Open

Open API 3 Specs Generation #5

dacloutier opened this issue Oct 5, 2023 · 2 comments

Comments

@dacloutier
Copy link

This is probably more of a limitation with the Open Api spec generation, but I'm curious as to why this is happening.

I'm building a proof of concept using the Open Api Schema annotations to generate the Open Api Spec document. And I get a spec document that doesn't seem to be usable to figure out the deserialization.

There doesn't seem to be a link between the CodifiedEnum and the Known Unknown objects.

Here's a code snippet of the Response class:

@ApiModel(
    description = "An order from a customer"
)
data class Order(
//...
    @Schema(
        name = "status",
        example = "DRAFT",
        description = "The status of the order",
        required = true
    )
    @Serializable(with = OrderStatus.CodifiedSerializer::class)
    val status: CodifiedEnum<OrderStatus, String>,
// ...
}

Here's a code snippet of the OrderStatus enum:

@ApiModel(
    description = "All order statuses"
)
enum class OrderStatus(override val code: String) : Codified<String> {
    DRAFT("DRAFT"), PROCESSED("PROCESSED"), CANCELLED("CANCELLED");

    object CodifiedSerializer : KSerializer<CodifiedEnum<OrderStatus, String>> by codifiedEnumSerializer()
}

The generated open api spec:

    Order:
      required:
      - id
      - status
      type: object
      properties:
        id:
          type: string
          description: The order identifier
          example: 2c93808457d787030157e02e7be22210
        status:
          $ref: '#/components/schemas/CodifiedEnumOrderStatusString'
    CodifiedEnumOrderStatusString:
      type: object
      description: The status of the order
      example: DRAFT
      allOf:
      - $ref: '#/components/schemas/CodifiedEnum'
    CodifiedEnum:
      type: object
    Known:
      required:
      - value
      type: object
      allOf:
      - $ref: '#/components/schemas/CodifiedEnumOrderStatusString'
      - type: object
        properties:
          value:
            type: string
      - $ref: '#/components/schemas/CodifiedEnum'
    Unknown:
      required:
      - value
      type: object
      allOf:
      - $ref: '#/components/schemas/CodifiedEnumOrderStatusString'
      - type: object
        properties:
          value:
            type: object
      - $ref: '#/components/schemas/CodifiedEnum'
@azabost
Copy link
Member

azabost commented Oct 8, 2023

Hi there. I'm not familiar with the OpenAPI specs, let alone its generation process, so sorry if my answer isn't helpful.

I wonder what exactly you would expect the generated spec to look like in your case.

I think that for the receiver, the use of the CodifiedEnum wrapper can act as a defense mechanism. Its use instead of the enum alone is a safeguard against unexpected compatibility problems or lack of proper API specification. That being said, I think you shouldn't need to expose (via OpenAPI spec) the fact you use CodifiedEnum as a protection measure. The clients of your API should send you one of the values you support (i.e. the "known" ones), shouldn't they?

Therefore, if I were you, I would probably aim to generate a specification that doesn't mention CodifiedEnum at all. Ideally, the specification should only mention the original enum OrderStatus but with the custom values (i.e. val code: String) instead of the enums' names (in your case, they are the same, but in general, they don't have to).

@miensol
Copy link
Member

miensol commented Oct 11, 2023

To add up to what @azabost said the primary aim of the Codified libs is to make it easier to keep code forward compatible regarding enums. That's more often the case of a client code, i.e. the code that receives enum values.

In other words if we expect our API clients to send us property attribute with fixed possible values (e.g. colour: "BLUE" or colour: "GREEN") then in the OpenAPI definition we have the standard enum definition. Even if in our DTOs we use Codified the OpenAPI definition should use regular enum definition. I suppose that should be possible currently by adding a properly configured @Schema annotation to the val status.

If we want our API to expose a property that has values from a known set and can have arbitrary values then I'd first check if it is possible to represent such a thing in the OpenAPI spec. If it is, we might need to add an extension to the Codified suite to handle that.

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

3 participants