Forum Discussion

mbeaudry1's avatar
mbeaudry1
New Contributor
5 years ago

Is it possible to have different #Ref Based on My API's Version

Hello,

I am new to swagger and using OpenAPI 3 and have come across something I can't find a reference or example to. Might be that I don't know the right key words to look for.

Here is a snippit of my YAML

 

servers:
- url: http://MySite:{Port}/MyRoute/{APIVersion}

  variables:

      APIVersion:
           enum:
                 - '1'
                 - '2'
                  - '3'
           default: '1'

Depending on what version of the API the user selects the request body schema description is different. 

Here is a small example of what I mean:

APIVersion 1 - {MyField:0}

APIVersion 2 - {MyField:0, MyNewField:1}

This structure evolves with APIVersions

 

Question: Is there a way to load a different reference depending on what APIVersion is selected by the user, or do I need to create a different YAML file for each version?

 

Something of this nature:

content:
   application/json:
       schema:

       if APIVersion = 1
          $ref: '#/components/schemas/ConfigStructure'

       else if APIVersion = 2

          $ref: '#/components/schemas/ConfigStructure2'

Thanks for your help and time,

Marc

 

 

 

 

 

  • Hi Marc,

     

    OpenAPI does not have a way to vary payloads based on server variables. The most consumer-friendly approach is to provide separate API definitions for different API versions.

     

    If you want to use a single API definition, you can try one of the following:

    1) Remove the version from the server URL and instead define different path versions as separate path items:

     

    paths:
      /v1/something:
        ...
      /v2/something:
        ...

     

    2) Use a single path with oneOf or anyOf to specify the possible schemas:

     

    paths:
      /something:
        post:
          requestBody:
            description: API version 1 uses `ConfigStructure` and version 2 uses `ConfigStructure2`.
            content:
              application/json:
                schema:
                  anyOf:
                    - $ref: '#/components/schemas/ConfigStructure'
                    - $ref: '#/components/schemas/ConfigStructure2'

     

    2) Use a single ConfigStructure schema containing all properties from all versions, and use the description or extensions to document which properties are required/returned by later versions of the API.

  • HKosova's avatar
    HKosova
    5 years ago

    Hi Marc,

     

    Your syntax is correct. This is a limitation of Swagger UI, currently it doesn't automatically generate examples for anyOf/oneOf schemas:

    https://github.com/swagger-api/swagger-ui/issues/3803

     

    As a workaround you can provide request and response examples manually:

    content:
      application/json:
        schema:
          anyOf:
            - $ref: '#/components/schemas/Foo'
            - $ref: '#/components/schemas/Bar'
        examples:
          ConfigStructure:
            value:
              prop1: value1
          ConfigStructureV3:
            value:
              prop2: value2

     

  • HKosova's avatar
    HKosova
    SmartBear Alumni (Retired)

    Hi Marc,

     

    OpenAPI does not have a way to vary payloads based on server variables. The most consumer-friendly approach is to provide separate API definitions for different API versions.

     

    If you want to use a single API definition, you can try one of the following:

    1) Remove the version from the server URL and instead define different path versions as separate path items:

     

    paths:
      /v1/something:
        ...
      /v2/something:
        ...

     

    2) Use a single path with oneOf or anyOf to specify the possible schemas:

     

    paths:
      /something:
        post:
          requestBody:
            description: API version 1 uses `ConfigStructure` and version 2 uses `ConfigStructure2`.
            content:
              application/json:
                schema:
                  anyOf:
                    - $ref: '#/components/schemas/ConfigStructure'
                    - $ref: '#/components/schemas/ConfigStructure2'

     

    2) Use a single ConfigStructure schema containing all properties from all versions, and use the description or extensions to document which properties are required/returned by later versions of the API.

    • mbeaudry1's avatar
      mbeaudry1
      New Contributor

      Thanks for the reply the proposed solution works, I used the second option.

      Here is my code:

      content:
      application/json:
      schema:
      anyOf:
      - $ref: '#/components/schemas/ConfigStructure'
      - $ref: '#/components/schemas/ConfigStructureV3'

       

      What I now observe is that my "Example Value" no longer appears. If I use one or the other of my defined components my example appears, but if I use the above syntax I get (no example available). The schema is behaving as it should I see both versions of my structure. 

       

      Question: Is my syntax incorrect, or do I need to specify the example separately from my reference? 

       

      Thanks for your help,

      Marc

       

       

      • HKosova's avatar
        HKosova
        SmartBear Alumni (Retired)

        Hi Marc,

         

        Your syntax is correct. This is a limitation of Swagger UI, currently it doesn't automatically generate examples for anyOf/oneOf schemas:

        https://github.com/swagger-api/swagger-ui/issues/3803

         

        As a workaround you can provide request and response examples manually:

        content:
          application/json:
            schema:
              anyOf:
                - $ref: '#/components/schemas/Foo'
                - $ref: '#/components/schemas/Bar'
            examples:
              ConfigStructure:
                value:
                  prop1: value1
              ConfigStructureV3:
                value:
                  prop2: value2