Skip to content

Adding merge construct #674

Closed
Closed
@fehguy

Description

@fehguy

Propose that we introduce a construct from JSON Schema draft-5, but not exactly per the draft-5 proposal.

Background

The allOf construct requires that all members be proper JSON Schemas. For JSON-Schema draft-5,
a $merge operator was proposed. The behavioral differences between the two include:

  • merge members do not need to be valid schemas
  • the $merge operator allows for subtraction of values
  • the $merge operator has operational order, which allows for a defined behavior when keys clash and have different values
  • the $merge operator is pre-processed, constructing a (valid) schema before validation is actually performed

The JSON schema draft has a different syntax than proposed. Why? It's too verbose, and supports a source and with syntax (i.e. merge two objects). We need to merge multiple objects, and the source, with is more wordy than we need.

Examples

Similar to allOf, but with partial schemas:

definitions:
  Dog:
    $merge:
      - $ref: '#/definitions/Animal'
      - description: a dog

  Animal:
    type: object
    properties:
      numberOfFeet:
        type: integer
        format: int32

result:

definitions:
  Dog:
    properties:
      numberOfFeet:
        type: integer
        format: int32
    description: a dog

In addition, since we can use $merge without full schemas, I propose a fragments section where non-validated schemas can be used.

parameters:
  - $merge:
    - $ref: '#/fragments/skip'
    - in: query
      description: the total records to skip
      minimum: null

fragments:
  skip:
    # this is a partial schema!  It's not a proper parameter
    name: skip
    type: integer
    format: int32
    minimum: 0

The effective result:

parameters:
  - in: query
    description: the total records to skip
    name: skip
    type: integer
    format: int32
    # note the minimum is removed by the `null`!!!

Modeling a common pattern

components:
  definitions:
    PaginatedResult:
      type: object
      properties:
        totalRecords:
          type: integer
          format: int32
        cursorId:
          type: string
    UserPaginatedResult:
      $merge:
        - $ref: '#/components/definitions/PaginatedResult'
        - properties:
            data:
              type: array
              items:
                $ref: '#/components/definitions/User'
    User:
      properties:
        name:
          type: string

Effective result:

components:
  definitions:
    UserPaginatedResult:
      type: object
      properties:
        totalRecords:
          type: integer
          format: int32
        cursorId:
          type: string
        # note `data` is merged, not replacing `properties`!!!
        data:
          type: array
          items:
            $ref: '#/components/definitions/User'

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions