Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

no-invalid-media-type-examples not working in a basic case with anyOf #1737

Open
LasneF opened this issue Sep 16, 2024 · 4 comments
Open

no-invalid-media-type-examples not working in a basic case with anyOf #1737

LasneF opened this issue Sep 16, 2024 · 4 comments
Labels
JSON Schema p2 Type: Bug Something isn't working

Comments

@LasneF
Copy link

LasneF commented Sep 16, 2024

Describe the bug

given a sample with anyOf and required statement example validation fails whereas it is valid

To Reproduce
validate the below OAS Spec (in the Additional context section)
launching redocly lint spec.yml

validation fails with the error
failed with 2 errors and 9 warnings.

it shoot about
schema: must NOT have unevaluated properties lastName

and
Example value must conform to the schema: must NOT have unevaluated properties address.

29 | },
30 | "example": {
31 | "address": "someWhere",

vs address is mentioned as required , looks it does not like the anyOf syntax

dropping the anyOf make it ok

Expected behavior

no validation warning toward this sample
sample has been tested with several json schema validator ( json-schema.hyperjump.io , json-everything.net , liquid'

Logs

Redocly Version(s)
redocly 1.25.2 ( on Windows)

Additional context

{
    "openapi": "3.1.0",
    "info": {
        "title": "this is the title",
        "description": "this is the description",
        "version": "1.0"
    },
    "license": {
        "description": "dd"
    },
    "servers": [
        {
            "url": "https://api.server.test/v1"
        }
    ],
    "paths": {
        "/v1/users": {
            "get": {
                "summary": "Get user info",
                "description": "Returns all details about a given user.",
                "operationId": "getUser",
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/User"
                                },
                                "example": {
                                    "address": "someWhere",
                                    "firstName": "John",
                                    "lastName": "Doe"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "empty"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "User": {
                "description": "Details of a user",
                "type": "object",
                "required": [
                    "address"
                ],
                "properties": {
                    "address": {
                        "type": "string"
                    }
                },
                "anyOf": [
                    {
                        "type": "object",
                        "required": [
                            "firstName",
                            "lastName"
                        ],
                        "properties": {
                            "firstName": {
                                "type": "string"
                            },
                            "lastName": {
                                "type": "string"
                            }
                        }
                    },
                    {
                        "type": "object",
                        "required": [
                            "name"
                        ],
                        "properties": {
                            "name": {
                                "type": "string"
                            }
                        }
                    }
                ]
            }
        }
    }
}
@LasneF LasneF added the Type: Bug Something isn't working label Sep 16, 2024
@tatomyr
Copy link
Contributor

tatomyr commented Sep 17, 2024

This is a duplicate of #1658. Feel free to add any additional details there.

@tatomyr tatomyr closed this as completed Sep 17, 2024
@tatomyr
Copy link
Contributor

tatomyr commented Sep 17, 2024

Wait, this is a separate issue. It goes away if we move address under each of the subschemas of anyOf. However, those syntaxes are equivalent, so the behaviour should be the same. The actual issue is that having properties and anyOf at the same time breaks the logic.

@tatomyr tatomyr reopened this Sep 17, 2024
@tatomyr tatomyr added the p2 label Sep 17, 2024
@jeremyfiel
Copy link
Contributor

jeremyfiel commented Oct 21, 2024

this requires the rules related to example validation to be modified

anyOf with a sibling additionalProperties: false doesn't allow any properties to be defined in that instance.
this line is causing that behavior.

https://github.com/Redocly/redocly-cli/blob/36161d76112779a5ce37289c9f063a35abb91a4e/packages/core/src/rules/ajv.ts#L26C7-L26C35

an example of what the schema is transformed to by Redocly

$schema: 'https://json-schema.org/draft/2020-12/schema'
properties:
  address:
    type: string
anyOf: [{}, {}]
additionalProperties: false // this is added by Redocly to all example schemas and it causes the example to fail, particularly when composition keywords are used at the root of the schema (anyOf, allOf, oneOf)

If we modify the rule, the example passes validation.

extends:
  - recommended

rules:
  no-invalid-media-type-examples:
    severity: warn
    allowAdditionalProperties: true
{
    "openapi": "3.1.0",
    "info": {
        "title": "this is the title",
        "description": "this is the description",
        "version": "1.0"
    },
    "license": {
        "description": "dd"
    },
    "servers": [
        {
            "url": "https://api.server.test/v1"
        }
    ],
    "paths": {
        "/v1/users": {
            "get": {
                "summary": "Get user info",
                "description": "Returns all details about a given user.",
                "operationId": "getUser",
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/User"
                                },
                                "examples": {
                                    "example": {
                                        "value": {
                                        "address": "someWhere",
                                        "firstName": "John",
                                        "lastName": "Doe"}
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "empty"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "User": {
                "description": "Details of a user",
                "type": "object",
                "required": [
                    "address"
                ],
                "properties": {
                    "address": {
                        "type": "string"
                    }
                },
                "anyOf": [
                    {
                        "type": "object",
                        "required": [
                            "firstName",
                            "lastName"
                        ],
                        "properties": {
                            "firstName": {
                                "type": "string"
                            },
                            "lastName": {
                                "type": "string"
                            }
                        }
                    },
                    {
                        "type": "object",
                        "required": [
                            "name"
                        ],
                        "properties": {
                            "name": {
                                "type": "string"
                            }
                        }
                    }
                ]
            }
        }
    }
}

@jeremyfiel
Copy link
Contributor

Btw.. the allowAdditionalProperties implementation is really only useful for OAS 3.0.x (json schema draft-04) when using the keyword additionalProperties

OAS 3.1.x. introduced full support of json schema 2020-12, and a new keyword unevaluatedProperties. this keyword has the ability to see into subschemas defined in a composition keyword (anyOf, allOf). if Redocly is going to constrain examples to use some form of unevaluatedProperties: false or additionalProperties: false, the proper keyword should be used for OAS 3.1.x schemas. >> unevaluatedProperties: false

an example with OAS 3.0.x

$schema: 'http://json-schema.org/draft-04/schema#'
properties:
  address:
    type: string
anyOf:
- properties:
    firstName: 
      type: string
- properties:
    name:
      type: string
additionalProperties: false // any instance will fail this schema because additionalProperties and anyOf are siblings. 

valid

address: test

invalid

address: test
firstName: larry

an example with OAS 3.1.x

$schema: 'https://json-schema.org/draft/2020-12/schema'
properties:
  address:
    type: string
anyOf:
-  properties:
     firstName: 
       type: string
-  properties:
     name:
       type: string
unevaluatedProperties: false // any instance with `address`, `firstName` or `name` will pass validation.. any other keyword included will fail validation

valid

address: test
firstName: larry
name: Jose

invalid

address: test
firstName: larry
name: Jose
age: 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
JSON Schema p2 Type: Bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants