1

Is it some how possible to specify constants/enums for properties inside referenced complex properties in OpenAPI?

I know for a simple string property I can specify some enum constants which I expect/ allow (as you can see in the example below at property sortOrder.

As you can see in this example I define the TestSearchModel with the property orderBy which is of a referenced type SortModel. SortModel is actually defined in another file of a framework (PS: I have access and the permission to change that framework for my needs). In this SortModel there is the property sortFieldName. I wish I could specify in TestSearchModel that I only allow e.g. ATTR_ONE. Is that possible?

Maybe you can image my use case. I would like to define a search operation which expects an input of type TestSearchModel. With this input it should be possible to define a column/property by with the sorting of the results found should be done.

openapi.yaml:

TestSearchModel:
  type: object
  properties:
    orderBy:
      $ref: "#/SortModel"
      enum: // allowed values of property sortFieldName in SortModel
        - ATTR_ONE
        - ATTR_TWO

SortModel:
  type: object
  properties:
    sortFieldName:
      type: string
    sortOrder:
      type: string
      enum:
        - ASC
        - DESC

This should be valid:

{
  "orderBy": {
      "sortFieldName": "ATTR_ONE",
      "sortOrder": "ASC"
  }
}

This should end up in an error, because 'ATTR_THREE' is not defined above in the allowed values:

  "sortModel": {
      "sortFieldName": "ATTR_THREE",
      "sortOrder": "ASC"
  }

I actually guess that with OpenAPI Spec this kind of specification is not possible. However may be you can provide some recommendations how to handle that.

I tried out the example above. OpenAPI generates the model classes without any error but (some kind of expected) without considering the limitation of the allowed strings for 'order by' property. I wish that an enum would be generated for ATTR_ONE and ATTR_TWO.

3 Answers3

1

It's possible. You'll need to add an extra schema alongside the $ref that defines a property with the same name on the same nesting level.

If you use OpenAPI 3.0.x or 2.0, make sure to wrap the $ref into allOf:

TestSearchModel:
  type: object
  properties:
    orderBy:
      allOf:
        - $ref: "#/SortModel"  # or "#/components/schemas/SortModel" or whatever the correct $ref path is

        - properties:          # <---
            sortFieldName:     # <---
              enum:
                - ATTR_ONE
                - ATTR_TWO

SortModel:
  type: object
  properties:
    sortFieldName:
      type: string
    sortOrder:
      type: string
      enum:
        - ASC
        - DESC

In OpenAPI 3.1, you can add keywords directly alongside the $ref:

# openapi: 3.1.0

TestSearchModel:
  type: object
  properties:
    orderBy:
      $ref: "#/SortModel"  # or "#/components/schemas/SortModel" or whatever the correct $ref path is
      properties:          # <---
        sortFieldName:     # <---
          enum:
            - ATTR_ONE
            - ATTR_TWO
Helen
  • 87,344
  • 17
  • 243
  • 314
  • Thanks your for the reply. As I use OpenAPI verion 3.0.1 I tried your first suggestion. But in this case class TestSearchModel is generated with the property sortModel which is of new generated type 'TestSearchModelSortModel' but it should be of type SortModel. Any hints on that? I will try to upgrade to OpenAPI 3.1.0 later this week. – Chris Brown Dec 12 '22 at 19:10
  • I think the only way to have the `sortModel` property be of type `SortModel` is to move the enum directly into the `SortModel` schema, as in @skidwiz's answer. But when using `allOf` + `$ref` to extend a schema, you're literally defining a new schema, which is reflected accordingly in the generated code. – Helen Dec 12 '22 at 19:31
0

The problem with your schema above is that openapi won't read anything after the $ref field. So, the enum value you have placed there is ignored. You can move the enum to your SortModel and it will be available:

TestSearchModel:
  type: object
  properties:
    orderBy:
      $ref: "#/SortModel"

SortModel:
  type: object
  properties:
    sortFieldName:
      type: string
      enum:
        - ATTR_ONE
        - ATTR_TWO
    sortOrder:
      type: string
      enum:
        - ASC
        - DESC

If you are trying to reuse the enum, you can do this via a reference, like this

TestSearchModel:
  type: object
  properties:
    orderBy:
      $ref: "#/SortFields"
SortModel:
  type: object
  properties:
    sortFieldName:
      $ref: "#/SortFields"
    sortOrder:
      $ref: "#/SortOrderTypes"
SortOrderTypes:
  type: string
  enum:
    - ASC
    - DESC
SortFields:
  type: string
  enum:
    - ATTR_ONE
    - ATTR_TWO
tbatch
  • 1,398
  • 10
  • 21
0

My solution is now:

TestSearchModel:
  type: object
  properties:
    orderBy:
      allOf:
        - $ref: "../../../../../src-gen/main/resources/openapi/model/base-search-model.yaml#/OrderByModel"
        - type: object
          properties:
            sortFieldName:
              enum:
                - name
                - geburtsdatum
                - justizbehoerde
                - modifikationszeit

where the file base-search-model.yaml is located in another maven artefact and we copy this file with maven into this project to src-gen/main/resources/openapi/model/base-search-model.yaml