Skip to content

Validation annotation of ParameterObject property applied to PathVariable with the same name, even in unrelated endpoints #3270

@cschierle

Description

@cschierle

Describe the bug

When the name of a property in a class used as @ParameterObject and the name of a @PathVariable collide (e.g. both named name), the @Pattern validation annotation of the parameter object's property name is applied to the name @PathVariable instead. This even spreads across unrelated controller classes also defining a path variable name.

To Reproduce
Steps to reproduce the behavior:
Created a fresh project with Spring initializer using

  • Kotlin version 2.3.20
  • SpringBoot version 4.0.5
  • Gradle version 9.4.1
  • springdoc-openapi-gradle-plugin version 1.9.0

SomeController defines two endpoints:

  • GET /somethings without any parameters
  • GET /somethings/{name}/names with a path variable name and a @ParameterObject that contains a property name with some regex validation declared via @Pattern

OtherController defines three endpoints:

  • GET /others without any parameters
  • GET /others/{name} with only the path variable name
  • GET /others/{name}/names with only the path variable name

Erroneous Result (shortened):

The regex pattern validation is applied to ALL name path variables in the generated OpenApi specification:

{
  "/somethings/{name}/names": {
    "get": {
      "parameters": [
        {
          "name": "name",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9]+$"
          }
        }
      ]
    }
  },
  "/others/{name}": {
    "get": {
      "parameters": [
        {
          "name": "name",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9]+$"
          }
        }
      ]
    }
  },
  "/others/{name}/members": {
    "get": {
      "parameters": [
        {
          "name": "name",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9]+$"
          }
        }
      ]
    }
  }
}

Sample Code

I provided the setup described above in this repository: https://github.com/cschierle/pattern-validation-demo

Expected behavior

ONLY the request parameter name of the endpoint GET /somethings/{name}/names should be validated with the regex pattern declared via @Pattern in the @ParameterObject. Endpoints from other controllers should be unaffected.

{
  "/somethings/{name}/names": {
    "get": {
      "parameters": [
        {
          "name": "name",
          "in": "query",
          "required": true,
          "schema": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9]+$"
          }
        }
      ]
    }
  },
  "/others/{name}": {
    "get": {
      "parameters": [
        {
          "name": "name",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ]
    }
  },
  "/others/{name}/members": {
    "get": {
      "parameters": [
        {
          "name": "name",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ]
    }
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions