Swagger schema properties ignored when using $ref – why?

TL;DR: $ref siblings are supported (to an extent) in OpenAPI 3.1. In previous OpenAPI versions, any keywords alongside $ref are ignored.

OpenAPI 3.1

Your definition will work as expected when migrated to OpenAPI 3.1. This new version is fully compatible with JSON Schema 2020-12, which allows $ref siblings in schemas.

openapi: 3.1.0
...

components:
  schemas:
    Time:
      type: string
      description: Time in 24 hour format "hh:mm".

    TimeInterval:
      type: object
      properties:
        lowerBound:
          # ------- This will work in OAS 3.1 ------- #
          $ref: "#/components/schemas/Time"
          description: Lower bound on the time interval.
          default: "00:00"
        upperBound:
          # ------- This will work in OAS 3.1 ------- #
          $ref: "#/components/schemas/Time"
          description: Upper bound on the time interval.
          default: "24:00"  

Outside of schemas – for example, in responses or parameters – $refs only allow sibling summary and description keywords. Any other keywords alongside these $refs will be ignored.

# openapi: 3.1.0

# This is supported
parameters:
  - $ref: '#/components/parameters/id'
    description: Entity ID

# This is NOT supported
parameters:
  - $ref: '#/components/parameters/id'
    required: true

Here’re some OpenAPI feature requests about non-schema $ref siblings that you can track/upvote:

OpenAPI 2.0 and 3.0.x

In these versions, $ref works by replacing itself and all of its sibling elements with the definition it is pointing at. That is why

      lowerBound:
        $ref: "#/definitions/Time"
        description: Lower bound on the time interval.
        default: "00:00"

becomes

      lowerBound:
        type: string
        description: Time in 24 hour format "hh:mm".

A possible workaround is to wrap $ref into allOf – this can be used to “add” attributes to a $ref but not override existing attributes.

      lowerBound:
        allOf:
          - $ref: "#/definitions/Time"
        description: Lower bound on the time interval.
        default: "00:00"

Another way is to use replace the $ref with an inline definition.

definitions:
  TimeInterval:
    type: object
    properties:
      lowerBound:
        type: string  # <------
        description: Lower bound on the time interval, using 24 hour format "hh:mm".
        default: "00:00"
      upperBound:
        type: string  # <------
        description: Upper bound on the time interval, using 24 hour format "hh:mm".
        default: "24:00"

Leave a Comment