NullableConverter produces an invalid nested type array for multi-type nullable schemas

Open Beginner friendly
#451 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
78/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
ruby

Research direction

Start with NullableConverter.normalize! and nullable_to_type_null!, then reproduce the issue with the schema shown in the report. Verify that a multi-type schema remains a flat type array containing null, and confirm the generated document is accepted by the affected validation tools.

Written by the indexing model from the issue text.

Description

Summary

When an OpenAPI 3.1+ schema contains multiple non-null types and null, NullableConverter does not round-trip it correctly.

A valid schema such as:

type: [string, number, boolean, object, array, "null"]

is rewritten as:

type:
  - [string, number, boolean, object, array]
  - "null"

The nested array is invalid JSON Schema and causes consumers such as oasdiff to reject the generated document.

Reproduction
require "rspec/openapi"

schema = {
  type: ["string", "number", "boolean", "object", "array", "null"],
}

RSpec::OpenAPI::NullableConverter.normalize!(schema)
RSpec::OpenAPI::NullableConverter.to_json_schema!(schema)

pp schema
Actual result
{
  type: [
    ["string", "number", "boolean", "object", "array"],
    "null",
  ],
}
Expected result
{
  type: ["string", "number", "boolean", "object", "array", "null"],
}

The conversion should preserve a flat array of type names.

Cause

nullable_to_type_null! always wraps the existing type:

[type, "null"]

After normalize!, type can already be an array containing multiple non-null types. Wrapping that array creates the invalid nested result.

The array case could append null instead:

case type
when nil
  "null"
when Array
  type | ["null"]
else
  [type, "null"]
end
Impact

oasdiff validate and oasdiff breaking fail while loading the generated contract:

json: cannot unmarshal array into field Schema.type of type string

This also prevents tools expecting a valid JSON Schema type array from consuming the generated OpenAPI document.

Workaround

Expressing the union with anyOf avoids the faulty conversion:

anyOf:
  - type: string
  - type: number
  - type: boolean
  - type: object
  - type: array
  - type: "null"
Environment
  • rspec-openapi: 0.33.0
  • The same converter implementation is present in 0.33.1
  • OpenAPI: 3.2.0
  • Ruby: 4.0.5
Dominant language
Ruby
Stars
509
Forks
76
Avg merge
13h 10m
Merged PRs (30d)
15

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from exoego/rspec-openapi

All issues in exoego/rspec-openapi

Similar issues

More Ruby issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.