spectral icon indicating copy to clipboard operation
spectral copied to clipboard

Nullable allOf construct doesn't work

Open philipbjorge opened this issue 4 years ago • 6 comments

Describe the bug I'm trying to describe a nullable ref and spectral is yelling at my examples being invalid

To Reproduce

Given this OpenAPI document:

openapi: 3.0.0
info:
  title: repro
  version: '1.0'
servers:
  - url: 'http://localhost:3000'
paths:
  '/users/{userId}':
    parameters:
      - schema:
          type: integer
        name: userId
        in: path
        required: true
        description: Id of an existing user.
    get:
      summary: Get User Info by User ID
      tags: []
      responses:
        '200':
          description: User Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
              examples:
                Get User Alice Smith:
                  value:
                    nullable_ref: null
        '404':
          description: User Not Found
      operationId: get-users-userId
      description: Retrieve the information of the user with the matching user ID.
components:
  schemas:
    Foo:
      type: object
      properties:
        bar:
          type: string
      required:
        - bar
    User:
      title: User
      type: object
      description: ''
      properties:
        nullable_ref:
          nullable: true
          allOf:
            - $ref: "#/components/schemas/Foo"
      required:
        - nullable_ref

Run this command:

npx @stoplight/spectral lint -q repro.yaml

Received:

29:35    error  oas3-valid-oas-content-example  `nullable_ref` property type should be object                            paths./users/{userId}.get.responses[200].content.application/json.examples['Get User Alice Smith'].value.nullable_ref

In the 6.0.0 alpha, I get an error:

Error: schema is invalid: data/properties/nullable_ref/type must be equal to one of the allowed values, data/properties/nullable_ref/type/0 must be equal to one of the allowed values, data/properties/nullable_ref/type must match a schema in anyOf
    at Ajv.validateSchema (/Users/philipbjorge/.npm/_npx/97956/lib/node_modules/@stoplight/spectral/node_modules/ajv/dist/core.js:251:23)
    at Ajv._addSchema (/Users/philipbjorge/.npm/_npx/97956/lib/node_modules/@stoplight/spectral/node_modules/ajv/dist/core.js:443:18)
    at Ajv.compile (/Users/philipbjorge/.npm/_npx/97956/lib/node_modules/@stoplight/spectral/node_modules/ajv/dist/core.js:145:26)
    at Object.exports.schema (/Users/philipbjorge/.npm/_npx/97956/lib/node_modules/@stoplight/spectral/dist/functions/schema/schema.js:37:33)
    at Object.o (eval at exports.evaluateExport (/Users/philipbjorge/.npm/_npx/97956/lib/node_modules/@stoplight/spectral/dist/ruleset/utils/evaluators.js:89:80), <anonymous>:1:1817)
    at Object.oasExample (eval at exports.evaluateExport (/Users/philipbjorge/.npm/_npx/97956/lib/node_modules/@stoplight/spectral/dist/ruleset/utils/evaluators.js:89:80), <anonymous>:1:3524)
    at Object.exports.lintNode (/Users/philipbjorge/.npm/_npx/97956/lib/node_modules/@stoplight/spectral/dist/runner/lintNode.js:29:33)
    at callback (/Users/philipbjorge/.npm/_npx/97956/lib/node_modules/@stoplight/spectral/dist/runner/runner.js:38:32)
    at JSONPath._handleCallback (/Users/philipbjorge/.npm/_npx/97956/lib/node_modules/@stoplight/spectral/node_modules/jsonpath-plus/dist/index-node-cjs.js:306:5)
    at JSONPath._trace (/Users/philipbjorge/.npm/_npx/97956/lib/node_modules/@stoplight/spectral/node_modules/jsonpath-plus/dist/index-node-cjs.js:337:10)

Expected behavior I expected this example to pass validation -- I thought the nullable: true, allOf approach was the appropriate way to create a nullable reference in OAS 3

Screenshots If applicable, add screenshots to help explain your problem.

Environment (remove any that are not applicable):

  • Library version: 5.9.1

philipbjorge avatar May 06 '21 15:05 philipbjorge

@philipbjorge Not a Json schema expert, however, I believe this cannot work because allOf expects all subschemas to be be valid. IOW, nullable_ref should first be an object before even being nullable.

I believe something like this should work.

    User:
      type: object
      properties:
        nullable_ref:
          oneOf:
            - $ref: "#/components/schemas/Foo"
            - type: null
      required:
        - nullable_ref

nulltoken avatar May 07 '21 18:05 nulltoken

Same issue:

      type: object
      required:
        - result
      properties:
        result:
          oneOf:
            - $ref: "#/components/schemas/Foo"
            - type: "null"
 95:21  error  oas3-schema  `type` property should be equal to one of the allowed values: `array`, `boolean`, `integer`, `number`, `object`, `string`. Did you mean `number`?.  components.schemas.Response.properties.result.oneOf[3].type

meme avatar May 12 '21 15:05 meme

@meme -- Not that it helps the primary issue, but I can share that the - type: "null" construct will only be valid with a OAS 3.1 doc

philipbjorge avatar May 12 '21 19:05 philipbjorge

We have this issue too. Comoforting to know at least that it's only an issue with spectral and that the OpenAPI file is apparently correct.

phoenixy1 avatar Aug 25 '21 03:08 phoenixy1

I think that I traced this back to an issue with ajv's nullable support:

  • https://github.com/ajv-validator/ajv/issues/1882

liamnichols avatar Jan 23 '22 15:01 liamnichols

updating to openapi 3.1.0 (from 3.0.0) fixed the issue for me. Thanks to : https://github.com/stoplightio/spectral/issues/1603#issuecomment-840048026

The OpenApi 3.0.0 states: "Note that there is no null type; instead, the nullable attribute is used as a modifier of the base type." Reference

checkin247 avatar Sep 05 '22 17:09 checkin247