redoc icon indicating copy to clipboard operation
redoc copied to clipboard

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

Open jeremyfiel opened this issue 1 year ago • 2 comments

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": "[email protected]"
        }
    },
    "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.

jeremyfiel avatar Jul 19 '23 21:07 jeremyfiel

I made some modifications to my schema and it changes the output closer to what I've requested.

image

This fixed part 2 of my issue.

I would still like to see labels applied when type is an array to allow the UI to select which type to view the constraints for. Currently, it shows the labels for the items array, but if the settingValue is not an array, this could be confusing to the user.

jeremyfiel avatar Jul 20 '23 19:07 jeremyfiel

@romanpryshliak please take a look. Thank you!

nalesnichok avatar Aug 08 '23 13:08 nalesnichok