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": false,
          "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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions