<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Polo</title>
    <description>The latest articles on Forem by Polo (@polo2).</description>
    <link>https://forem.com/polo2</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F797425%2F4d894bd1-6579-430c-addd-b80771e962ee.jpeg</url>
      <title>Forem: Polo</title>
      <link>https://forem.com/polo2</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/polo2"/>
    <language>en</language>
    <item>
      <title>How to use and document polymorphism in API</title>
      <dc:creator>Polo</dc:creator>
      <pubDate>Fri, 28 Apr 2023 12:44:00 +0000</pubDate>
      <link>https://forem.com/bump/how-to-use-and-document-polymorphism-in-api-21o4</link>
      <guid>https://forem.com/bump/how-to-use-and-document-polymorphism-in-api-21o4</guid>
      <description>&lt;p&gt;Don't Repeat Yourself. Be DRY! Anyone who ever had to manually correct thousand of flyers printed for an event,&lt;br&gt;
with an obvious typo in date or location, could confirm it.&lt;br&gt;
It would have been easier to review the original file before running the presses.&lt;/p&gt;

&lt;p&gt;Every developer knows this rule (or should, at least).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Asserting that code should be easy to change is akin to stating that children&lt;br&gt;
should be polite; the statement is impossible to disagree with.&lt;br&gt;
&lt;em&gt;(Source: Practical Object-Oriented design, Sandi Metz)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As described in this very interesting book, &lt;em&gt;easy to change&lt;/em&gt; code&lt;br&gt;
can be defined with:&lt;br&gt;
&lt;em&gt;small changes in requirements require correspondingly small changes in code&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;And to do so, Single Responsibility, Don't Repeat Yourself and Single Source of Truth&lt;br&gt;
are very important design patterns to develop smart applications, easy to use, easy to develop, easy to maintain, and thus improve the Developer Experience.&lt;/p&gt;

&lt;p&gt;On this page, I'll do my best to explain and illustrate how polymorphism can be used in API development to help achieve these big objectives.&lt;br&gt;
And I'm glad to share with this post a synthesis of what I learned for months about polymorphism, composition and inheritance support in API documentations, based on OpenAPI and AsyncAPI specifications.&lt;/p&gt;
&lt;h2&gt;
  
  
  Polymorphism concept
&lt;/h2&gt;

&lt;p&gt;We don't want to have two different behaviors for very similar objects, some parts of code&lt;br&gt;
and logic would be duplicated.&lt;br&gt;
Point about polymorphism is to extract what is common by nature, and what is specific to this instance.&lt;/p&gt;

&lt;p&gt;For the following, we'll need an example to illustrate all these situations.&lt;/p&gt;

&lt;p&gt;Let's consider a real estate agency application, whose purpose is to offer accommodations for rent.&lt;br&gt;
We can consider that the main object for this agency is accommodation.&lt;/p&gt;

&lt;p&gt;But what type of accommodation?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;House, with a garden, a tiled roof, a total size, monthly rent and an address.&lt;/li&gt;
&lt;li&gt;Apartment, with a specific floor, maybe parking slots and elevator, a total size, monthly rent and an address.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wait… &lt;em&gt;Déjà-vu&lt;/em&gt;, right?&lt;/p&gt;

&lt;p&gt;House and Apartment have many shared informations, that are related to what they are by nature:&lt;br&gt;
&lt;em&gt;A place where people live by giving some money.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Indeed, both house and apartment have shared information: a monthly rent, an address,&lt;br&gt;
information about total area.&lt;/p&gt;

&lt;p&gt;But only an apartment has a specific floor. And we don't usually care about&lt;br&gt;
roof tiles unless you live in a house.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a8mcaB0D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://storage.googleapis.com/bump-blog-resources/bump-polymorphism-in-api/Polymorphism_accomodation.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a8mcaB0D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://storage.googleapis.com/bump-blog-resources/bump-polymorphism-in-api/Polymorphism_accomodation.png" alt="polymorphism diagram" width="800" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are many solutions for implementing that into your codebase,&lt;br&gt;
based on your team, language, framework, architecture, opinions about typed VS object oriented language…&lt;/p&gt;

&lt;p&gt;But as said someone wise about API:&lt;/p&gt;

&lt;p&gt;“Do what the hell you want with your backend, but expose a simple and documented API”&lt;/p&gt;
&lt;h2&gt;
  
  
  Polymorphism in API
&lt;/h2&gt;

&lt;p&gt;Polymorphism in API refers to the possibility to use the same endpoint for&lt;br&gt;
similar but different objects. Indeed, it's a good practice&lt;br&gt;
to avoid different endpoints to do somehow the same action.&lt;/p&gt;

&lt;p&gt;For example, in a request body, we should favor a single endpoint to handle requests for different data types or structures.&lt;br&gt;
And for a Response, it's practical to allow a single endpoint to return different representations of a resource, based on the request made by the client.&lt;/p&gt;

&lt;p&gt;This gives a more flexible and scalable API design, as well as reducing the amount of endpoint duplications.&lt;/p&gt;

&lt;p&gt;In our example, without polymorphism, we could imagine two different endpoints to add&lt;br&gt;
a new accommodation to the real estate agency database.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;POST /house&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /apartment&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both would require a request body, with a lot of fields regarding house or apartment.&lt;br&gt;
But we know that there are some shared information between these two object,&lt;br&gt;
because they have something in common by nature: both are a place to live for (at least) humans.&lt;/p&gt;

&lt;p&gt;A good practice here is to expose only one endpoint for this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;POST /accommodation&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Regarding the data provided to the request body, result would be to create&lt;br&gt;
either a House, or an Apartment.&lt;/p&gt;

&lt;p&gt;The request body for creating an apartment might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"apartment"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;707&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rue de Clery, 75002 Paris, France"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"floor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"elevator"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While the request body for creating a house might look like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"house"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;149&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chemin du haut Pertuzou, 38160 Saint-Verand, France"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"garden_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"roof_tiles_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Clay"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"solar_panels_power"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see here property &lt;code&gt;type&lt;/code&gt; is used to find out what kind of accommodation has to be created.&lt;br&gt;
It can be very well documented for REST or Event-Driven APIs, we'll come to this later.&lt;/p&gt;

&lt;p&gt;In this way, polymorphism in REST APIs allows for a more flexible and scalable API design, as well as reducing the amount of endpoint duplications.&lt;/p&gt;

&lt;p&gt;But API is consumed. And API consumers have to be very aware of this polymorphism.&lt;br&gt;
At Bump.sh, we are convinced that the best solution is to have a very nice documentation for your API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yZzkH2US--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://storage.googleapis.com/bump-blog-resources/bump-polymorphism-in-api/doc%2520-%2520House%2520without%2520discriminator.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yZzkH2US--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://storage.googleapis.com/bump-blog-resources/bump-polymorphism-in-api/doc%2520-%2520House%2520without%2520discriminator.png" alt="new house request" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;source: &lt;a href="https://bump.sh/demo/hub/support/doc/accommodation-polymorphism"&gt;https://bump.sh/demo/hub/support/doc/accommodation-polymorphism&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's see how to properly document polymorphic resources with OpenAPI&lt;br&gt;
or AsyncAPI specifications, based on JSON Schema.&lt;/p&gt;
&lt;h2&gt;
  
  
  Polymorphism in API documentation
&lt;/h2&gt;
&lt;h3&gt;
  
  
  JSON schema
&lt;/h3&gt;

&lt;p&gt;Polymorphism is natively supported by JSON Schema, to handle schema composition.&lt;/p&gt;

&lt;p&gt;As described in &lt;a href="https://json-schema.org/understanding-json-schema/reference/combining.html"&gt;JSON schema documentation&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;JSON Schema includes a few keywords for combining schemas together (…)&lt;br&gt;
The keywords used to combine schemas are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;allOf: (AND) Must be valid against all of the subschemas&lt;/li&gt;
&lt;li&gt;anyOf: (OR) Must be valid against any of the subschemas&lt;/li&gt;
&lt;li&gt;oneOf: (XOR) Must be valid against exactly one of the subschemas&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;First combinator &lt;code&gt;allOf&lt;/code&gt; is not really concerned by this article.&lt;br&gt;
Indeed, in our example, it's difficult to imagine an accommodation being&lt;br&gt;
both a house &lt;em&gt;and&lt;/em&gt; an apartment. Currently, it can be summarized as a merge&lt;br&gt;
between schemas described behind &lt;code&gt;allOf&lt;/code&gt; list.&lt;/p&gt;

&lt;p&gt;What is concerned by polymorphism are alternatives, &lt;code&gt;anyOf&lt;/code&gt; (OR) or &lt;code&gt;oneOf&lt;/code&gt; (XOR).&lt;/p&gt;

&lt;p&gt;Now let's see how to document alternatives, with JSON schema, in OpenAPI and AsyncAPI&lt;br&gt;
specifications. Good news, since both are based on JSON schema, same rules&lt;br&gt;
can be applied (except about &lt;code&gt;discriminator&lt;/code&gt;, we'll handle it very soon).&lt;/p&gt;

&lt;p&gt;We could imagine an OpenAPI request body, or response content,&lt;br&gt;
or even AsyncAPI message payload or headers, each schema is described with a&lt;br&gt;
&lt;code&gt;Schema Object&lt;/code&gt;. Alternatives could be inserted in a lot of places:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# OpenAPI&lt;/span&gt;
&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;/accommodations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create an accommodation&lt;/span&gt;
      &lt;span class="na"&gt;requestBody&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;application/json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="c1"&gt;# insert schemas alternatives here&lt;/span&gt;
      &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;200&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Accommodation has been created.&lt;/span&gt;
          &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;application/json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# insert schemas alternatives here&lt;/span&gt;

&lt;span class="c1"&gt;# AsyncAPI&lt;/span&gt;
&lt;span class="na"&gt;channels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;accommodations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;subscribe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Accommodation creation&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="c1"&gt;# insert schemas alternatives here&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="c1"&gt;# insert schemas alternatives here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll consider the OpenAPI request body to create an accommodation.&lt;br&gt;
Either house, either apartment.&lt;/p&gt;
&lt;h3&gt;
  
  
  OpenAPI example
&lt;/h3&gt;

&lt;p&gt;Please see below the complete example of &lt;code&gt;POST /accommodation&lt;/code&gt; request body,&lt;br&gt;
used for &lt;a href="https://bump.sh/demo/hub/support/doc/accommodation-polymorphism"&gt;this documentation&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;/accommodation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create an accommodation&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;Example about polymorphism in API.&lt;/span&gt;
        &lt;span class="s"&gt;This endpoint 'POST /accommodation' can be used to&lt;/span&gt;
        &lt;span class="s"&gt;create either apartment, either house.&lt;/span&gt;
      &lt;span class="na"&gt;requestBody&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;application/json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;oneOf&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/House"&lt;/span&gt;
                &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/Apartment"&lt;/span&gt;

&lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schemas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Accommodation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;type&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;size&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;monthly_rent&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;address&lt;/span&gt;
      &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
        &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;
        &lt;span class="na"&gt;monthly_rent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;number&lt;/span&gt;
        &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;Apartment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;allOf&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/Accommodation"&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
          &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;floor&lt;/span&gt;
          &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;floor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;
            &lt;span class="na"&gt;collective_heating_system&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boolean&lt;/span&gt;
            &lt;span class="na"&gt;elevator&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boolean&lt;/span&gt;
            &lt;span class="na"&gt;parking_spots&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;
    &lt;span class="na"&gt;House&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;allOf&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/Accommodation"&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
          &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;garden_size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;
              &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Area, in square meters (m²).&lt;/span&gt;
            &lt;span class="na"&gt;roof_tiles_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
              &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Multiple types exist for roof tiles.&lt;/span&gt;
            &lt;span class="na"&gt;solar_panels_power&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;
              &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Installed photovoltaic power, in Watt (Wc). _Yes, modern house should have solar panels_&lt;/span&gt;
            &lt;span class="na"&gt;basement_size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Combinators &lt;code&gt;anyOf&lt;/code&gt; or &lt;code&gt;oneOf&lt;/code&gt; have to be used at first level,&lt;br&gt;
with an array of related schemas, here &lt;code&gt;House&lt;/code&gt; and &lt;code&gt;Apartment&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Inheritance &amp;amp; DRY
&lt;/h3&gt;

&lt;p&gt;Here, there are three different schemas listed in &lt;code&gt;/components/schemas/*&lt;/code&gt; list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Accommodation&lt;/code&gt;, with every properties shared by House and Apartment, as accommodation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Apartment&lt;/code&gt;,  with every properties specific to an apartment&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;House&lt;/code&gt;,  with every properties specific to a house.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Indeed, we know that both House and Apartment share a lot of details, by inheriting&lt;br&gt;
from parent object &lt;code&gt;Accommodation&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can see it in each schema &lt;code&gt;House&lt;/code&gt; and &lt;code&gt;Apartment&lt;/code&gt;, with the merging combinator&lt;br&gt;
&lt;code&gt;allOf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;House has every properties from Accommodation (type, size, monthly rent, and address),&lt;br&gt;
and some specific house properties: garden size, roof tiles type or solar panels power…&lt;br&gt;
And same for Apartment.&lt;/p&gt;

&lt;p&gt;This usage of parent object, and &lt;code&gt;allOf&lt;/code&gt; combinator is a useful&lt;br&gt;
solution to avoid code duplication here, and apply Inheritance pattern in JSON schema.&lt;/p&gt;
&lt;h3&gt;
  
  
  Extract title
&lt;/h3&gt;

&lt;p&gt;In both OpenAPI and AsyncAPI documentation, it's strongly recommended to avoid&lt;br&gt;
inline schemas, &lt;em&gt;ie&lt;/em&gt; to favor schemas described behind an internal reference &lt;code&gt;$ref&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What is crucial is the ability to extract a title for each alternative.&lt;br&gt;
With &lt;code&gt;$ref&lt;/code&gt;, title is defined from last element of path:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;$ref: "#/components/schemas/House"&lt;/code&gt;: extracted title is &lt;code&gt;House&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$ref: "#/components/schemas/Apartment"&lt;/code&gt;: extracted title is &lt;code&gt;Apartment&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But we can also favor to extract this title from the explicit &lt;code&gt;title&lt;/code&gt; field, if provided in the schema object.&lt;/p&gt;

&lt;p&gt;For example if third and very lightweight alternative accommodation was added&lt;br&gt;
without reference:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;requestBody&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;application/json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;oneOf&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/House"&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/Apartment"&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
            &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Yurt&lt;/span&gt;
            &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;type&lt;/span&gt;
            &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
              &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This alternative would be named &lt;code&gt;Yurt&lt;/code&gt;.&lt;br&gt;
If we had omitted the &lt;code&gt;title: Yurt&lt;/code&gt; attribute, Bump.sh would have to generate a title based on type and index&lt;br&gt;
(here it would be &lt;code&gt;'object-2'&lt;/code&gt;)&lt;/p&gt;
&lt;h3&gt;
  
  
  Discriminator
&lt;/h3&gt;

&lt;p&gt;Note: for this section, every alternative has to be object, or array of objects,&lt;br&gt;
a schema with properties. If no properties, no discriminator.&lt;/p&gt;

&lt;p&gt;Now's the time to clarify this required &lt;code&gt;type&lt;/code&gt; property, used on purpose for&lt;br&gt;
every schemas inheriting from &lt;code&gt;Accommodation&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;It's a good practice to use a specific property to distinct which schema&lt;br&gt;
has to be used.&lt;/p&gt;

&lt;p&gt;This can be considered as a hint for the API. If &lt;code&gt;type&lt;/code&gt; is explicit,&lt;br&gt;
there is no need for backend to validate if provided data are compliant&lt;br&gt;
with &lt;code&gt;House&lt;/code&gt; or &lt;code&gt;Apartment&lt;/code&gt; . Indeed, it would be weird (and costly)&lt;br&gt;
to detect &lt;code&gt;garden_size&lt;/code&gt; or &lt;code&gt;parking_slots&lt;/code&gt; and implicitly guess accommodation type.&lt;/p&gt;

&lt;p&gt;Because this is missing in JSON schema support, both OpenAPI and AsyncAPI&lt;br&gt;
have introduced a specific keyword for this, &lt;code&gt;discriminator&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;cf documentations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.asyncapi.com/docs/reference/specification/v2.5.0#schemaComposition"&gt;AsyncAPI 2.x discriminator&lt;/a&gt; (as String)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://spec.openapis.org/oas/v2.0.html#fixed-fields-12"&gt;OpenAPI 2.0 discriminator&lt;/a&gt; (as String)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://spec.openapis.org/oas/v3.1.0.html#discriminator-object"&gt;OpenAPI 3.x discriminator&lt;/a&gt; (as Object)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First solution is to use string format (supported by OpenAPI 2.x, aka Swagger,&lt;br&gt;
and AsyncAPI).&lt;/p&gt;

&lt;p&gt;In every alternative with properties, one property is identified as the discriminator.&lt;br&gt;
This property has to be required, and of course, it has to be shared between all alternatives, so&lt;br&gt;
with our example, it's relevant to use shared &lt;code&gt;Accommodation&lt;/code&gt; schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Accommodation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
  &lt;span class="na"&gt;discriminator&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type&lt;/span&gt;
  &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;type&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;size&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;monthly_rent&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;address&lt;/span&gt;
  &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="c1"&gt;# …&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thus, correct alternative is chosen by matching provided value for &lt;code&gt;type&lt;/code&gt;&lt;br&gt;
with each alternative title:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;House&lt;/code&gt; value for &lt;code&gt;type&lt;/code&gt; clarifies that &lt;code&gt;House&lt;/code&gt; schema will be used&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Apartment&lt;/code&gt; value for &lt;code&gt;type&lt;/code&gt; clarifies that &lt;code&gt;Apartment&lt;/code&gt; schema will be used&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Flat&lt;/code&gt; value for &lt;code&gt;type&lt;/code&gt; clarifies that &lt;code&gt;Apartment&lt;/code&gt; schema will… wait, what??&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You read it well. Sometime, API maintainers could expect an other value instead of&lt;br&gt;
alternative title to ensure schemas matching.&lt;/p&gt;

&lt;p&gt;And that's why &lt;code&gt;discriminator&lt;/code&gt; support is different for OpenAPI 3.1:&lt;/p&gt;

&lt;p&gt;In this case, &lt;code&gt;discriminator&lt;/code&gt; is an object, with two fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;propertyName&lt;/code&gt;, string value of the property used as discriminator&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mapping&lt;/code&gt;, a hash to give explicit values&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And in this case, it has to be defined at the same level as the combinator.&lt;/p&gt;

&lt;p&gt;In our example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;requestBody&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;application/json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;oneOf&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/House"&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/Apartment"&lt;/span&gt;
        &lt;span class="na"&gt;discriminator&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;propertyName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type&lt;/span&gt;
          &lt;span class="na"&gt;mapping&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;house&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/House"&lt;/span&gt;
            &lt;span class="na"&gt;flat&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#/components/schemas/Apartment"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is visible in generated documentation, where allowed value is explicitly&lt;br&gt;
defined as either &lt;code&gt;flat&lt;/code&gt;, either &lt;code&gt;house&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7mgYHIlT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://storage.googleapis.com/bump-blog-resources/bump-polymorphism-in-api/doc%2520-%2520Apartment%2520with%2520discriminator.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7mgYHIlT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://storage.googleapis.com/bump-blog-resources/bump-polymorphism-in-api/doc%2520-%2520Apartment%2520with%2520discriminator.png" alt="new flat request" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bump.sh/demo/hub/support/doc/accommodation-polymorphism/with-discriminator/operation/operation-post-accommodation#operation-post-accommodation-body"&gt;See it live&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Polymorphism and inheritance are essential patterns to improve your API design and&lt;br&gt;
avoid code duplication (no Single Source of Truth when your code is duplicated).&lt;/p&gt;

&lt;p&gt;Both OpenAPI and AsyncAPI have nice tools to support them, you just need to choose &lt;code&gt;oneOf&lt;/code&gt; these specifications.&lt;/p&gt;

&lt;p&gt;I hope this post/article/guide/tutorial/page (&lt;code&gt;anyOf&lt;/code&gt; these formats) did help you on your &lt;em&gt;polymorphism in API&lt;/em&gt; journey.&lt;/p&gt;

&lt;p&gt;Writing this article was not easy, but I can assure you that implementing all the support for all these polymorphism concept&lt;br&gt;
in both OpenAPI and AsyncAPI was not a long, quiet river.&lt;br&gt;
That's why I'm very glad to reveal that these combinators &lt;code&gt;anyOf&lt;/code&gt; and &lt;code&gt;oneOf&lt;/code&gt; are now fully supported in every documentation hosted on Bump.sh, as&lt;br&gt;
detailed &lt;a href="https://docs.bump.sh/product-updates/2022/11/14/polymorphism/"&gt;in our changelog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy polymorphism,&lt;br&gt;
Polo&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>api</category>
      <category>openapi</category>
      <category>asyncapi</category>
    </item>
  </channel>
</rss>
