Forum Discussion

cscott952's avatar
cscott952
New Contributor
6 years ago
Solved

Required parameters from multiple schemas

Hello,

I'm trying to enforce required parameters in both the 'check_single' and 'check_set' below. The required parameters work when passing when they match the 'check_single', but I haven't been successful in the require being enforced in the 'check_set'. The only difference between to the 2 is that 'check_set' allows consumers to send a list. This is being used in conjunction with Flask/Connexion in Python 3.6.

 

I've been through all the applicable examples and docs I can find, but I'm still stuck.

 

openapi: 3.0.0
info:
  version: 1.0.0
  title: check create

paths:
  /monitor/v1/submit:
    post:
      summary: "submit checks"
      operationId: "create_v1.publish_body_v1"
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/check'
      responses:
        '201':
          description: OK
components:
  schemas:
    check:
      title: check request single
      anyOf:
          - $ref: '#/components/schemas/check_single'
          - $ref: '#/components/schemas/check_set'
      required: ["hostname", "team_name"]
      properties:
        hostname:
          type: string
        team_name:
          type: string
        check_definition:
          type: object
          required: ["command", "subscriptions", "interval", "publish", "handlers", "metadata"]
          properties:
            command:
              type: string
            subscriptions:
              type: array
              items:
                type: string
            interval:
              type: integer
            publish:
              type: boolean
            handlers:
              type: array
              items:
                type: string
            metadata:
              type: object
              required: ["name", "namespace", "labels"]
              properties:
                name:
                  type: string
                namespace:
                  type: string
                labels:
                  type: object
                  required: ["type", "environment", "application"]
                  properties:
                    type:
                      type: string
                      example: "Either dynamic or static"
                      enum:
                        - dynamic
                        - static
                    environment:
                      type: string
                      description: "Environment lab for IEM. This is the environment as know by IEM"
                    application:
                      type: string
                      description: "Application name as IEM knows it"
                    service_key:
                      type: string
                      description: "PD service key for incident handling"
                    notification_channel:
                      type: string
                      description: "incident generation tool"
                    remediation_action:
                      type: string
                      description: "remediation action"
                    notifcation_enable:
                      type: boolean
                      description: "incident/notification generation enabled"
    check_single:
      title: check request single
      type: object
    check_set:
      title: set of checks
      type: array
      description: "check set"
      items:
          type: object
  • The use of `anyOf` means that the input would need to match one (or more) of the sub-schemas described in it.

     

    The problem is that you have `anyOf` with two different types - `object` and `array`. The `required` and `properties` are at the same level of the `anyOf` - that means that they would only be applied `check_single` as its type is `object`. When you put type `array` alongside `required` or `properties`, the latter two would have no impact as they have no meaning with tpe `array`.

     

    So what can you do to solve this?

     

    Take the 'single' object definition and extract it to a model. For our purpose, let's call it `MyObject`.

     

    So:

     

    MyObject:
      type: object
      required: [...]
      properties: ...

     

     

    And then you can define `check` as this:

     

    check:
      anyOf:
        - $ref: '#/components/schemas/MyObject'
        - type: array
          items:
    $ref: '#/components/schemas/MyObject

     

    In this case, you may want to use `oneOf` instead, because there will never be case where a compared input will have both.

     

3 Replies

  • The use of `anyOf` means that the input would need to match one (or more) of the sub-schemas described in it.

     

    The problem is that you have `anyOf` with two different types - `object` and `array`. The `required` and `properties` are at the same level of the `anyOf` - that means that they would only be applied `check_single` as its type is `object`. When you put type `array` alongside `required` or `properties`, the latter two would have no impact as they have no meaning with tpe `array`.

     

    So what can you do to solve this?

     

    Take the 'single' object definition and extract it to a model. For our purpose, let's call it `MyObject`.

     

    So:

     

    MyObject:
      type: object
      required: [...]
      properties: ...

     

     

    And then you can define `check` as this:

     

    check:
      anyOf:
        - $ref: '#/components/schemas/MyObject'
        - type: array
          items:
    $ref: '#/components/schemas/MyObject

     

    In this case, you may want to use `oneOf` instead, because there will never be case where a compared input will have both.

     

    • cscott952's avatar
      cscott952
      New Contributor

      Thanks a lot! I have it mostly working, and have a much better understanding of how to overlay schemas.  That said, is there any way to get the response to include what required property is in violation when an incorrect JSON payload is sent?  In my old spec, the 'single' schema would return what property/element was in violation.  What I have now just returns  ... ' is not valid under any of the given schemas'.  The client receives this:

       

      {<JSON request body> is not valid under any of the given schemas",
        "status": 400,
        "title": "Bad Request",
        "type": "about:blank"
      }
      

       

       

      • RonRatovsky's avatar
        RonRatovsky
        Moderator

        That's more likely a question to the Connexion team. It's not our project and we don't have enough knowledge to help with it. However, they are very responsive so if you file a ticket on the project's repo, I'm sure they'll get back to you.