stoplightio / spectral

A flexible JSON/YAML linter for creating automated style guides, with baked in support for OpenAPI v3.1, v3.0, and v2.0 as well as AsyncAPI v2.x.
https://stoplight.io/spectral
Apache License 2.0
2.43k stars 235 forks source link

oas3-valid-schema-example nullable cannot be used without type #2494

Closed davidkeaveny closed 3 months ago

davidkeaveny commented 1 year ago

When using an OpenAPI specification where a property is defined using a $ref and that property is marked as nullable, the linter is returning an error when an example is given.

The following OAS3.0 specification illustrates the problem:

components:
  schemas:
    address:
      type: object
      description: A geographical address.
      properties:
        street:
          type: string
          description: The street address of the location.
          nullable: true
        suburb:
          type: string
          description: The suburb of the location.
          nullable: true
        city:
          type: string
          description: The city of the location.
          nullable: true
    createPersonalDetails:
      type: object
      description: |
        A request to create new personal details.
      example:
        homeAddress:
          street: 1 Short Street
          suburb: Kensington
          city: Sydney
        personalEmailAddress: john.smith@gmail.com
      properties:
        homeAddress:
          description: The person's home address.
          allOf:
            - $ref: '#/components/schemas/address'
          nullable: true
        emailAddress:
          type: string
          description: The person's email address.
          format: email
          nullable: true

This returns the following error:

61:15 error  oas3-valid-schema-example  "nullable" cannot be used without "type"  components.schemas.createPersonalDetails.example

I will get the same error if I:

I can only clear the error if I either remove the example altogether, or if I change the definition to:

      properties:
        homeAddress:
          $ref: '#/components/schemas/address'

but that means the field is no longer nullable, and I have lost the description - neither of these are good solutions.

Any thoughts?

miriamgreis commented 1 year ago

@davidkeaveny I tried it out and there are better solutions than the ones you suggested. I worked from the error message stating that nullable cannot be used without a type.

Here are my solutions:

  1. Move nullable to the address (which is possible not what you want if you reuse it somewhere else):

    components:
    schemas:
    address:
      type: object
      description: A geographical address.
      properties:
        ....
      nullable: true
    createPersonalDetails:
      type: object
      ...
      properties:
        homeAddress:
          description: The person's home address.
          allOf:
            - $ref: '#/components/schemas/address'
        emailAddress:
          type: string
          description: The person's email address.
          format: email
          nullable: true
  2. Don't use allOff, but instead use anyOf for the homeAddress:

    homeAddress:
    description: The person's home address.
    anyOf:
    - $ref: '#/components/schemas/address'
    - type: object
      nullable: true

I hope this helps to solve your problem.