JSON and object inheritance

10,460

It's been possible to combine schemas using keywords such as oneOf, allOf, anyOf and get the payload validated since JSON schema v1.0.

https://spacetelescope.github.io/understanding-json-schema/reference/combining.html

However, composition has been enhanced by the keyword discriminator incorporated on OpenAPI (former Swagger) to barely support polymorphism. In OpenAPI 3.0, this support has been enhanced by the addition of oneOf keyword.

Your inheritance could be modeled using a combination of oneOf (for choosing one of the children) and allOf (for combining parent and child).

paths:
  /customers:
  post:
   requestBody:
    content:
      application/json:
        schema:
          oneOf:
            - $ref: '#/components/schemas/Individual
            - $ref: '#/components/schemas/Organization
          discriminator:
            propertyName: customer_type
   responses:
     '201':
       description: Created
components:
  schemas:
    Customer:
      type: object
      required:
        - customer_type
        - externalID
      properties:
        customer_type:
          type: string
        externalID:
          type: integer
      discriminator:
        property_name: customer_type
    Individual:
      allOf:
        - $ref: "#/components/schemas/Customer"
        - type: object
        - properties:
          firtName
            type: string
          lastName
            type: string
    Organisation:
      allOf:
        - $ref: "#/components/schemas/Customer"
        - type: object
        - properties:
          organisationName
            type: string
          listingName
            type: string

https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaComposition

18/02/2020 Edit:
For generating Java code using Jackson, OpenAPITools has seemingly been fixed by the PR #5120

Share:
10,460
Raghavan
Author by

Raghavan

Updated on June 05, 2022

Comments

  • Raghavan
    Raghavan almost 2 years

    We are trying to move from SOAP to REST and we stumbled across this issue Here party can be of type Individual or Organization.

    Sample XMLs

    <customer>
      <details>
        <party xsi:type="Individual">
          <externalID>ABC123</externalID>
          <firstname>John</firstname>
          <lastname>Smith</lastname>
        </party>
      </details>
    </customer>
    
    <customer>
      <details>
        <party xsi:type="Organization">
          <externalID>APPLE</externalID>
          <organizationName>Apple Inc</organizationName>
          <listingName>APPLE</listingName>
        </party>
      </details>
    </customer>
    

    However when we move to JSON representation of the same, we encounter the problem where the inheritance information is lost

    JSON Sample

    {
      "customer": {
        "details": {
          "party": {
            "externalID": "ABC123",
            "firstname": "John",
            "lastname": "Smith"
          }
        }
      }
    }
    
    {
      "customer": {
        "details": {
          "party": {
            "externalID": "APPLE",
            "organizationName": "Apple Inc",
            "listingName": "APPLE"
          }
        }
      }
    }
    

    So when we convert the JSON back to Java object using libraries like Gson, we loose the definition of Individual or Organization.

    While one of the workaround is to build additional services to retrieve the "details" returning the concrete types (Individual or Organization), is there any other approach to handle this in JSON?

  • emft
    emft over 6 years
    It's true that OAS allows this. However, there is no support for the feature to be displayed in Swagger UI (link), and I think a feature is of limited use if you can't show it to anyone.