codified icon indicating copy to clipboard operation
codified copied to clipboard

Open API 3 Specs Generation

Open dacloutier opened this issue 2 years ago • 2 comments

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'

dacloutier avatar Oct 05 '23 20:10 dacloutier

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).

azabost avatar Oct 08 '23 19:10 azabost

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.

miensol avatar Oct 11 '23 06:10 miensol