Skip to content

v3.2: Allow Media Type Object re-use #4728

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
wants to merge 2 commits into
base: v3.2-dev
Choose a base branch
from

Conversation

handrews
Copy link
Member

@handrews handrews commented Jun 16, 2025

[NOTE: See this later comment for a why this PR has been changed to only support $ref-ing Media Type Objects, and not Encoding Objects.]

Add the Media Type Object and Encoding Object to the Components Object, and allow a Reference Object anywhere they are allowed. To ensure that re-usable Objects can be documented clearly, add a description field to both Objects. [Note: If adding description is more controversial than just supporting re-use, I could be persuaded to drop it.]

One important thing to do as a release approaches is to try to use the new features more. As I have done this, I've realized that our increased usage and functionality of Media Type and Encoding Objects (which now handle streaming JSON, and are expected to handle a wider variety of multipart media types and be more useful with XML) make re-use of those objects a much more compelling prospect. While your average application/json Media Type Object is trivial, once you start using more complex media types, the duplication becomes substantial.

Explanation and Examples

One use case might come from @jeremyfiel who, IIRC, works with an API where multipart/mixed usage that combines JSON metadata with binary data is common. Depending on how complex and common that format is, the media type object might be worth re-using in many places. We're expanding the support for multipart a lot, and in general multipart Media Type Objects are quite complex, with many Encoding Objects (which may have substantial commonality themselves if similar parts are used in different multipart configurations) plus Example Objects.

But to bring things back to a concrete example, here is a pattern that was at one time fairly common- allowing querying either through the URL query string, or through putting the query contents in the body of a POST in case the URL got too long (although here I am showing QUERY instead of POST).

Assume both of the examples to follow start with these components (I pulled them out to make the length comparisons more obvious):

openapi: 3.2.0 
info:
  title: API
components:
  schemas:
    PetFields:
      enum: 
      - name
      - petType
      - color
      - gender
      - breed
    Pet:  
      propertyNames:
        $ref: '#/components/schemas/PetFields'
      additionalProperties:
        type: string
      required:
      - name
      - petType
    ListForQuery:
      type: array 
      items:
        type: string      
    PetQueryLists:
      additionalProperties:
        $ref: '#/components/schemas/ListForQuery'
      propertyNames:
        $ref: '#/components/schemas/PetFields'
  examples:
    CatSearch:
      summary: Search for Persian or Ragamuffin cats
      dataValue:
        petType:
        - Cat
        breed:
        - Persian
        - Ragamuffin
      serializedValue: petType=Cat&breed=Persian,Ragamuffin
  responses:
    Pets:
      content:
        application/json:
          schema:
            type: array
              items:
                $ref: '#/components/schemas/Pet'

Here it is with re-use, at 50 additional lines:

...
components:
   ...
  parameters:
    PetQuery:
      name: pets
      in: querystring
      content:
        application/x-www-form-urlencoded:
          $ref: '#/components/mediaTypes/PetQuery'
      examples:
        CatSearch:
          $ref: '#/components/examples/CatSearch'
  mediaTypes:
    PetQuery:
      description: A query format for pets.
      schema:
        $ref: '#/components/schemas/PetQueryLists'
      encoding:
        name: 
          style: form
          explode: false
        petType:
          style: form
          explode: false
        color:
          style: form
          explode: false
        gender:
          style: form
          explode: false
        breed:
          style: form
          explode: false
      examples:
        CatSearch:
          $ref: '#/components/examples/CatSearch'
paths:
  /pets:
    get:
      parameters:
      - $ref: '#/components/parameters/PetQuery'
      responses:
        "200":
          $ref: '#/components/responses/Pets'
    query:
      requestBody:
        content:
          application/x-www-form-urlencoded:
            $ref: '#/components/mediaTypes/PetQuery'
      responses:
        "200":
          $ref: '#/components/responses/Pets'

Without re-use, it takes 66 additional lines. However, there is another wrinkle if we wanted to put in some descriptive text, which we'll look at afterwards [without Encoding Object re-use included, the descriptive text issue is no longer relevant]:

...
components:
   ...
  parameters:
    PetQuery: 
      name: pets
      in: querystring
      content:
        application/x-www-form-urlencoded:
          schema:
            $ref: '#/components/schemas/PetQueryLists'
          encoding:
            name:
              style: form
              explode: false
            petType:
              style: form
              explode: false
            color:
              style: form
              explode: false
            gender:
              style: form
              explode: false
            breed:
              style: form
              explode: false
          examples:
            CatSearch:
              $ref: '#/components/examples/CatSearch'
      examples:
        CatSearch:
          $ref: '#/components/examples/CatSearch'
paths:
  /pets:
    get:
      parameters:
      - $ref: '#/components/parameters/PetQuery'
      responses:
        "200":
          $ref: '#/components/responses/Pets'
    query:
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PetQueryLists'
            encoding:
              name:
                style: form
                explode: false
              petType:
                style: form
                explode: false
              color:
                style: form
                explode: false
              gender:
                style: form
                explode: false
              breed:
                style: form
                explode: false
            examples:
              CatSearch:
                $ref: '#/components/examples/CatSearch'
      responses:
        "200":
          $ref: '#/components/responses/Pets'
  • schema changes are included in this pull request
  • schema changes are needed for this pull request but not done yet
  • no schema changes are needed for this pull request

@handrews handrews requested review from a team as code owners June 16, 2025 02:02
@handrews handrews added the media and encoding Issues regarding media type support and how to encode data (outside of query/path params) label Jun 16, 2025
@handrews handrews changed the title v3.3: Allow Media Type and Encoding re-use v3.2: Allow Media Type and Encoding re-use Jun 16, 2025
@handrews handrews added this to the v3.2.0 milestone Jun 16, 2025
@handrews
Copy link
Member Author

Accidentally pushed an intermediate commit, had to force-push to fix. This should be correct now- also fixed the title as this is proposed for 3.2 based on trying to use new 3.2 features in non-trivial ways.

Copy link
Contributor

@ralfhandl ralfhandl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, minor nits

ralfhandl
ralfhandl previously approved these changes Jul 18, 2025
@ralfhandl ralfhandl requested a review from a team July 18, 2025 08:36
@handrews
Copy link
Member Author

Hmm... I have run into a problem with $ref-ing Encoding Objects, at least if we add support for examples to them. And it feels like we should given that we want people to use Encoding Objects for style/explode/etc. in the query string.

Examples of individual form fields include the name (e.g. foo=bar, not just bar), but the name is not part of the Encoding Object. That's fine if the Encoding Object MUST be inline, as that keeps it under the parent encoding field which does have the name. But if it's $ref-able, it would be used for fields with different names, and any example/examples field that we added to the Encoding Object would only be right for one of the names. 😵‍💫

The Header Object would have the same problem, except header examples do not include the header name (see PR #4800 for why). So it's fine to $ref Header Objects.

But at the moment, it feels like we can either $ref Encoding Objects, or we can add example support to them, and I lean towards example support.

Of course it is possible to just do an example of the whole query string or multipart document at the Media Type Object level, but I feel like limiting examples to that might be problematic. I need to think on it more.

miqui
miqui previously approved these changes Jul 19, 2025
@ralfhandl ralfhandl dismissed their stale review July 19, 2025 14:49

To avoid accidental merge

@lornajane
Copy link
Contributor

I'd be in favour of adding the extra components field for just media types if that's simpler? It seems like it would have the widest use case too (at least the way I write OpenAPI!)

@handrews
Copy link
Member Author

@lornajane given the potential confusion with Encoding Objects I'm leaning that way. I will update this PR. There are also always Overlays if people really want to re-use Encoding Objects and can manage the name-vs-example thing in their own way.

Add the Media Type Object to the Components Object,
and allow a Reference Object anywhere it is allowed.

To ensure that re-usable Objects can be documented clearly, add
a `description` field.
@handrews handrews changed the title v3.2: Allow Media Type and Encoding re-use v3.2: Allow Media Type Object re-use Jul 19, 2025
@handrews
Copy link
Member Author

With apologies for the rebase, it was easier to git reset --soft and re-add the Media Type parts than to manually remove the Encoding Object parts. This should now only address Media Type Object re-use.

@handrews handrews requested a review from a team July 19, 2025 19:06
Copy link
Contributor

@ralfhandl ralfhandl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, minor nit

Co-authored-by: Ralf Handl <ralf.handl@sap.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
media and encoding Issues regarding media type support and how to encode data (outside of query/path params)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants