Redocly / Redocly/redoc

Property labels are incorrect when `type` is an array, OAS 3.1.x+

Open
#2,364 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Type: Enhancement
Dominant language
TypeScript
Stars
25.9k
Forks
2.4k
Avg merge
13h 10m
Merged PRs (30d)
4

Description

Describe the bug
When using OAS 3.1.x+ and JSON Schema external schemas the labels provided on Redoc are incorrect when using an array of type keywords.

The schema expects type: ["string", "number", "array", "boolean", "integer"] .

https://json-schema.org/draft/2020-12/json-schema-validation.html#section-6.1.1

There are two issues here with the parsing of type when it's an array of values
  1. You cannot assume the property is an array when the items keyword is defined. The settingValue could be any of the types listed. JSON Schema says if an assertion is present but does not have a corresponding applicator keyword, the instance shall be considered a passing schema. In laymen terms, if the instance is a type: string, an items or number/integer assertion minimum would be ignored because a string does not have the ability to have an array schema asserted upon itself or a minimum value.

  2. When settingValue is an array, the first branch of the oneOf is not date or uri with the type listed in the array but rather any of the listed types in oneOf/0 or an object in oneOf/1. The anyOf sibling in the oneOf/0 index indicates acceptable string/format combinations when the instance is of type: string

This is only applicable to OAS 3.1.0 because OAS 3.0.x does not allow the type keyword to have an array

Expected behavior

I don't have a mock up available but I'll try my best to explain the view I would expect.

settingValue string or number or array or boolean or integer
This is functionally equivalent to using an anyOf, I think it would be nice to have selectable labels in the same way it works for composition keywords (allOf, oneOf, anyOf)

Then, if the array type is selected, the oneOf labels will appear with each branch, in this case, again with string or boolean or number or integer or object, if the string label is selected, then the anyOf branches will appear.

Minimal reproducible OpenAPI snippet(if possible)

{
    "openapi": "3.1.0",
    "info": {
        "title": "A test api",
        "version": "1.0.0",
        "contact": {
            "name": "jeremy",
            "email": "nothanks@yahoo.com"
        }
    },
    "servers": [],
    "tags": [
        {
            "name": "test api",
            "description": "a sample api"
        }
    ],
    "paths": {
        "/test": {
            "get": {
                "description": "test",
                "tags": [
                    "test api"
                ],
                "parameters": [],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": false,
                                    "properties": {
                                        "settingValue": {
                                            "description": "Setting values - each setting can hold multiple values",
                                            "type": [
                                                "string",
                                                "number",
                                                "array",
                                                "boolean",
                                                "integer"
                                            ],
                                            "items": {
                                                "oneOf": [
                                                    {
                                                        "type": [
                                                            "boolean",
                                                            "number",
                                                            "integer"
                                                        ]
                                                 },
                                                 {
                                                 "anyOf": [
                                                            {
                                                                "$schema": "http://json-schema.org/draft-04/schema#",
                                                                "title": "date",
                                                                "description": "The string representation of the date value using the ISO-8601:2000 format.  Supports complete date YYYY-MM-DD or partial, e.g. YYYY or MM-DD",
                                                                "type": "string",
                                                                "pattern": "^([12]\\d{3}(-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[0-1]))?)|(([12]\\d{3}-)?(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[0-1]))$"
                                                            },
                                                            {
                                                                "$schema": "http://json-schema.org/draft-04/schema#",
                                                                "title": "URI",
                                                                "description": "The URI of the related entity, typically used to represent any internet or social network address",
                                                                "type": "string",
                                                                "format": "uri"
                                                            }
                                                        ]
                                                    },
                                                    {
                                                        "allOf": [
                                                            {
                                                                "$schema": "http://json-schema.org/draft-04/schema#",
                                                                "title": "CodeType_v01",
                                                                "description": "The code for the related entity.  If this is a coded value, both code and name should be used. If this is just a string value, only name is necessary.",
                                                                "type": "object",
                                                                "properties": {
                                                                    "code": {
                                                                        "description": "The code for the related entity",
                                                                        "$schema": "http://json-schema.org/draft-04/schema#",
                                                                        "type": "string",
                                                                        "pattern": "^[a-zA-Z0-9.$-_/ ]+$"
                                                                    },
                                                                    "name": {
                                                                        "description": "The short description of the related code used as a coded name",
                                                                        "type": "string"
                                                                    }
                                                                }
                                                            },
                                                            {
                                                                "type": "object",
                                                                "properties": {
                                                                    "selectedIndicator": {
                                                                        "description": "Indicates if a particular code was selected",
                                                                        "$schema": "http://json-schema.org/draft-04/schema#",
                                                                        "title": "IndicatorType",
                                                                        "type": "boolean"
                                                                    }
                                                                }
                                                            }
                                                        ]
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                },
                                "examples": {
                                    "array_with_a_plain_string_value": {
                                        "value": {
                                            "settingValue": [
                                                "jeremy"
                                            ]
                                        }
                                    },
                                    "array_with_a_date_string": {
                                        "value": {
                                            "settingValue": [
                                                "2020-01-01"
                                            ]
                                        }
                                    },
                                    "array_with_a_uri_string": {
                                        "value": {
                                            "settingValue": [
                                                "https://www.redoc.com"
                                            ]
                                        }
                                    },
                                    "array_with_an_object_schema": {
                                        "value": {
                                            "settingValue": [
                                                {
                                                    "code": "test",
                                                    "name": "onetwo",
                                                    "selectedIndicator": true
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

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

Additional context
Add any other context about the problem here.

Contributor guide

Open the contributing guide

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.

Research direction

Start by loading the minimal OpenAPI 3.1.0 snippet in Redoc and tracing how array-valued type keywords and items are converted into property labels. Verify the rendering for scalar types, array items, oneOf, and anyOf; done means labels reflect all allowed types without treating every schema with items as an array.

Written by the indexing model from the issue text.

Assessment

Tech stack
openapi, typescript
Domain
documentation, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.