Swagger and JSON Patch

16,586

Solution 1

For this simple case, I would use a JSON Patch object to describe the operations to make on the target. Here is an example of a JSON Patch Swagger API.

paths:
  /users/{GUID}:
    patch:
      summary: Update a user
      parameters:
        - name: GUID
          in: path
          required: true
          type: string
          format: GUID
          description: The GUID of a specific user 
        - name: JsonPatch
          in: body
          required: true
          schema:
            $ref: "#/definitions/PatchRequest"
      responses:
        '200':
          description: Successful response
          schema:
            $ref: "#/definitions/User"
definitions:
  PatchRequest:
    type: array
    items:
      $ref: "#/definitions/PatchDocument"
  PatchDocument: 
    description: A JSONPatch document as defined by RFC 6902 
    required:
     - "op"
     - "path"
    properties: 
     op: 
      type: string 
      description: The operation to be performed 
      enum:
       - "add"
       - "remove"
       - "replace"
       - "move"
       - "copy"
       - "test"
     path: 
      type: string 
      description: A JSON-Pointer 
     value: 
      type: object 
      description: The value to be used within the operations.
     from: 
      type: string 
      description: A string containing a JSON Pointer value.

Solution 2

For OpenApi 3.0.x the structure of the .yaml file has changed. A valid definition could look like:

components:
  requestBodies:
    PatchBody:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PatchBody'

  schemas:
    PatchBody:
      type: array
      items:
        $ref: "#/components/schemas/PatchDocument"

    PatchDocument:
      type: object
      description: A JSONPatch document as defined by RFC 6902 
      required:
       - "op"
       - "path"
      properties: 
       op: 
        type: string 
        description: The operation to be performed 
        enum:
         - "add"
         - "remove"
         - "replace"
         - "move"
         - "copy"
         - "test"
       path: 
        type: string 
        description: A JSON-Pointer 
       value: 
        type: object 
        description: The value to be used within the operations.
       from: 
        type: string 
        description: A string containing a JSON Pointer value.            

    patch:
      parameters:
        - $ref:  '#/components/parameters/objectId'
      requestBody:
        $ref: '#/components/requestBodies/PatchBody'
      responses:
        ...

Solution 3

Since the JSON Patch format is well defined by RFC 6902 I think it would be sufficient (at least for OpenAPI 3) to specify the content type defined in the RFC, and since it seems to be necessary to define either a schema or example (at least in my swagger editor), to also specify type: string and format: JSON Patch or format: RFC 6902.

It doesn't make sense to redefine a format that is already well defined by the RFC.

Example:

paths:
  /users/{GUID}:
    patch:
      summary: Update a user
      parameters:
      - name: GUID
        in: path
        required: true
        type: string
        format: GUID
        description: The GUID of a specific user 
      requestBody:
        content:
          application/json-patch+json:
            schema:
              type: string
              format: RFC 6902
Share:
16,586
user8222014
Author by

user8222014

Updated on June 21, 2022

Comments

  • user8222014
    user8222014 almost 2 years

    I have the following object structure in my database

    {
        partnerName: '24 Fitness',
        supportedProducts: [
            'FitBit',
            'Protein Powder'
        ]
    },
    

    where the key value supportedProducts can be modified from the client side.

    I am constructing a PATCH API method using swagger documentation to support the above functionality. But I am unsure of the patch object definition, as documentation doesn't provide an detailed example of constructing a PATCH.

    The current definition that I have ends up in error upon execution and looks like as following

     "patch":{
        "description":"Update supported products for a partner",
        "operationId":"Update supported products",
        "parameters":[
          {
            "name": "partnerName",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "supportedProducts",
            "in": "body",
            "required": true,
            "schema":{
              "$ref":"#/definitions/PatchRequest"
            }
          }
        ],
        "responses":{
          "200":{
            "description": "product updated"
          },
          "404":{
            "description": "Not Found"
          }
        }
    
      "definitions": {
        "PatchRequest":{
          "type": "object",
          "required":[
            "partnerName",
            "supportedProducts"
          ],
          "properties":{
            "partnerName":{"type": "string"},
            "supportedProducts":{
              "type": "array",
              "items":{"type": "string"}
            }
          }
    
        }
      }