OpenAPI - different schema per operation on same resource

Viewed 226

I'm using OpenAPI 3.0 to describe an API where each resource has a subtly different schema based on its operation. Essentially certain properties are editable and/or required based on whether it's a POST or PUT request.

Is there a better way to do this other than specify a schema for each operation like this? (where field2 is readOnly on the PUT)

Ideally, I'd like to specify the schema (i.e. all the properties) in one place and then override some properties (e.g. readOnly) on each operation.

{
   "paths":{
      "/users":{
         "put":{
            "responses":{
               "200":{
                  "$ref":"#/components/schemas/users_put"
               }
            }
         },
         "post":{
            "responses":{
               "200":{
                  "$ref":"#/components/schemas/users_post"
               }
            }
         }
      }
   },
   "components":{
      "schemas":{
         "users_post":{
            "properties":{
               "field1":{
                  "readOnly":true,
                  "type":"integer"
               },
               "field2":{
                  "type":"string"
               }
            }
         },
         "users_put":{
            "properties":{
               "field1":{
                  "readOnly":true,
                  "type":"integer"
               },
               "field2":{
                  "type":"string",
                  "readOnly":true
               }
            }
         }
      }
   }
}
1 Answers

As far as I know, there is no override mechanism in openapi/swagger models. But composition (extending) models is available.

Since in your example you need to update only readOnly directives (which means you mark properties that's available only in responses) try other approach when you describe requests and responses separately.

Such in your example the response for put and post methods would be the same (because they both have field1 and field2), and only put will have request (because in post all fields is readOnly):

(I use yaml for brevity, but it's easy convert to json back)

paths:
  "/users":
    put:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/users_put_request'
      responses:
        '200':
          "$ref": "#/components/schemas/users_response"
    post:
      responses:
        '200':
          "$ref": "#/components/schemas/users_response"
components:
  schemas:
    users_response:
      field1:
        type: integer
      field2:
        type: integer

    users_put_request:
      field2:
          type: string

Probably with this approach the different parts of models is describe explicitly.

Related