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

jsonpath-plus does not work correctly only(?) when evaluated in Spectral rule. #2158

Closed
Qbaloz opened this issue May 16, 2022 · 2 comments · Fixed by #2173
Closed

jsonpath-plus does not work correctly only(?) when evaluated in Spectral rule. #2158

Qbaloz opened this issue May 16, 2022 · 2 comments · Fixed by #2173
Assignees
Labels
released t/bug Something isn't working

Comments

@Qbaloz
Copy link

Qbaloz commented May 16, 2022

Describe the bug
There are some jsonpath-plus paths which are not correctly evaluated in Spectral. According to https://jsonpath.com/ site both versions of my paths should work, but unfortunately one of them could not be found in document.

To Reproduce

  1. Given this OpenAPI/AsyncAPI document:
{
  "openapi": "3.0.2",
  "info": {
    "title": "Swagger Petstore - OpenAPI 3.0",
    "description": "This is a sample Pet Store Server based on the OpenAPI 3.0 specification.  You can find out more about\nSwagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!\nYou can now help us improve the API whether it's by making changes to the definition itself or to the code.\nThat way, with time, we can improve the API in general, and expose some of the new features in OAS3.\n\nSome useful links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)",
    "termsOfService": "http://swagger.io/terms/",
    "contact": {
      "email": "[email protected]"
    },
    "license": {
      "name": "Apache 2.0",
      "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
    },
    "version": "1.0.11"
  },
  "externalDocs": {
    "description": "Find out more about Swagger",
    "url": "http://swagger.io"
  },
  "servers": [
    {
      "url": "/api/v3"
    }
  ],
  "tags": [
    {
      "name": "pet",
      "description": "Everything about your Pets",
      "externalDocs": {
        "description": "Find out more",
        "url": "http://swagger.io"
      }
    }
  ],
  "paths": {
    "/pet/findByStatus": {
      "get": {
        "tags": [
          "pet"
        ],
        "summary": "Finds Pets by status",
        "description": "Multiple status values can be provided with comma separated strings",
        "operationId": "findPetsByStatus",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Status values that need to be considered for filter",
            "required": false,
            "explode": true,
            "schema": {
              "type": "string",
              "default": "available",
              "enum": [
                "available",
                "pending",
                "sold"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Pet"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Pet"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Pet"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Pet"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid status value"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "petstore_auth": [
              "write:pets",
              "read:pets"
            ]
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "Tag": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "name": {
            "type": "string"
          }
        },
        "xml": {
          "name": "tag"
        }
      },
      "Pet": {
        "required": [
          "name",
          "photoUrls"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "example": 10
          },
          "name": {
            "type": "string",
            "example": "doggie"
          },
          "photoUrls": {
            "type": "array",
            "xml": {
              "wrapped": true
            },
            "items": {
              "type": "string",
              "xml": {
                "name": "photoUrl"
              }
            }
          },
          "tags": {
            "type": "array",
            "xml": {
              "wrapped": true
            },
            "items": {
              "$ref": "#/components/schemas/Tag"
            }
          },
          "status": {
            "type": "string",
            "description": "pet status in the store",
            "enum": [
              "available",
              "pending",
              "sold"
            ]
          }
        },
        "xml": {
          "name": "pet"
        }
      }
    },
    "requestBodies": {
      "Pet": {
        "description": "Pet object that needs to be added to the store",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Pet"
            }
          },
          "application/xml": {
            "schema": {
              "$ref": "#/components/schemas/Pet"
            }
          }
        }
      }
    },
    "securitySchemes": {
      "petstore_auth": {
        "type": "oauth2",
        "flows": {
          "implicit": {
            "authorizationUrl": "https://petstore3.swagger.io/oauth/authorize",
            "scopes": {
              "write:pets": "modify pets in your account",
              "read:pets": "read your pets"
            }
          }
        }
      }
    }
  }
}
  1. Given this rules:
    "test-working-jsonpath": {
      "formats": [
        "oas3"
      ],
      "given": "$.paths.*.*.responses.401,404",
      "severity": "error",
      "then": [
        {
          "field": "content",
          "function": "falsy"
        }
      ]
    },
    "test-not-working-jsonpath": {
      "formats": [
        "oas3"
      ],
      "given": "$.paths.*.*.responses[401,404]",
      "severity": "error",
      "then": [
        {
          "field": "content",
          "function": "falsy"
        }
      ]
    }
  1. After running Spectral Validation only the first rule with given:
 "given": "$.paths.*.*.responses.401,404",

will throw error. Second rule with given:

"given": "$.paths.*.*.responses[401,404]",

will say that everything is ok.
According to https://jsonpath.com/ boths paths are good, so I'm not really sure why it is not working correctly with "[...].

Expected behavior
Jsonpaths with square brackets should be correctly interpreted in Spectral.

Used Spectral libraries:

    "@stoplight/spectral-core": "^1.12.1",
    "@stoplight/spectral-ruleset-bundler": "^1.2.1"

Additional context
I found some other paths for example:

$.components.[?(@.enum)]~

which I had to convert to:

$...components.[?(@.enum)]~

to make them work in Spectral.

@Qbaloz Qbaloz changed the title jsonpath-plus does not work correctly only(?) when evaluated in rule. jsonpath-plus does not work correctly only(?) when evaluated in Spectral rule. May 16, 2022
@marbemac marbemac added the t/bug Something isn't working label Jun 1, 2022
@P0lip
Copy link
Contributor

P0lip commented Jun 1, 2022

@Qbaloz
Spectral doesn't use jsonpath-plus by default, hence that slight difference in behavior.

if you need a quick fix, you can use $.paths.*.*.responses["401","404"]. The issue here is that we don't cast 401 and 404 to strings, so there's no match.

Regarding the second example you posted - I'd say this is rather a bug in jsonpath-plus itself, as I don't think .[ should act as ..[ in this particular case, but to remain compatible with jsonpath-plus, I'm eager to change that behavior.

@stoplight-bot
Copy link
Collaborator

🎉 This issue has been resolved in version @stoplight/spectral-core-v1.12.3 🎉

The release is available on npm package (@latest dist-tag)

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
released t/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants