{"id":14986628,"url":"https://github.com/ystrauch/swagger-object-validator","last_synced_at":"2025-04-11T20:32:01.663Z","repository":{"id":39030100,"uuid":"84651791","full_name":"YStrauch/swagger-object-validator","owner":"YStrauch","description":"Node-Module to validate your model against a swagger spec and receive in-depth error traces","archived":false,"fork":false,"pushed_at":"2022-06-23T15:10:46.000Z","size":743,"stargazers_count":29,"open_issues_count":3,"forks_count":8,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-25T18:16:39.648Z","etag":null,"topics":["polymorphism","swagger","swagger-spec","swagger2","validation","validator"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/YStrauch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-11T13:27:29.000Z","updated_at":"2024-03-06T18:39:22.000Z","dependencies_parsed_at":"2022-09-19T22:13:21.038Z","dependency_job_id":null,"html_url":"https://github.com/YStrauch/swagger-object-validator","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YStrauch%2Fswagger-object-validator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YStrauch%2Fswagger-object-validator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YStrauch%2Fswagger-object-validator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YStrauch%2Fswagger-object-validator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/YStrauch","download_url":"https://codeload.github.com/YStrauch/swagger-object-validator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248476369,"owners_count":21110264,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["polymorphism","swagger","swagger-spec","swagger2","validation","validator"],"created_at":"2024-09-24T14:13:15.109Z","updated_at":"2025-04-11T20:31:56.642Z","avatar_url":"https://github.com/YStrauch.png","language":"TypeScript","readme":"# What?\nValidate an Object against a given [swagger (V2.0)](http://swagger.io/specification/) API definition.\n\u003e A swagger definition specifies an API with requests and data models, and there are a lot of compilers to create server and client skeletons. There are some tools that validate the requests that were sent to the server, but surprisingly there is a huge lack of (good) validators for response bodies.\n\nJust test it quickly and be amazed:\n\n[![Try it on RunKit](https://badge.runkitcdn.com/swagger-object-validator.svg)](https://npm.runkit.com/swagger-object-validator)\n\n\n# Why this and not some other tool?\nThe API is awesome, it gives you easy and full control over what's happening:\n- Every error has a detailed stack trace so you can find where and what is wrong easily\n- Stack traces are in a format that allows computer programs to understand what's wrong without parsing strings\n- You can add your own rules or ignore certain errors\n- Other tools do not like splitted specifications (via *$ref*)\n- Most other tools do not implement very special constraints (like regex, int32/int64, minItems...)\n\n# Features\n## Validation\nThe following swagger specifications are validated:\n- All the basic stuff like Numbers, Strings, Enums, Arrays, Objects\n- Required properties\n- Int32/Int64, Float/Double, Booleans\n- Dates and Date-Times\n- Maps *(additionalProperties)*\n- Inheritance *(allOf)*\n- Polymorphism *(discriminator)*\n- Custom polymorphism that uses enums\n- All kinds of references ($ref)\n\n## Flexible API\n- Load your swagger spec from a JSON/yaml file, the interwebs *or* load it yourself and do your stuff first\n- Validate your object either by name or by a specification object\n- Get useful **stack traces** of all the validation errors that occured\n- Stack traces are readable by both programs and humans\n- Need to add custom validation rules or ignore certain errors? No problem!\n- TypeScript support\n\n# Quick start\n\n*Please ensure that the swagger spec itself is valid to prevent unexpected errors, this module does not verify the spec itself.*\n\nLet's assume you got a pet from your pet store and want to validate it.\n\n## Using TypeScript\n\n```ts\nimport * as SwaggerValidator from 'swagger-object-validator';\nlet validator = new SwaggerValidator.Handler('https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v2.0/yaml/petstore.yaml');\n\nlet pet = {\n    id: 123,\n    name: 'Doge'\n};\nvalidator.validateModel(pet, 'Pet', (err, result) =\u003e {\n    console.log(result.humanReadable());\n});\n\n```\n\n## Using JavaScript\n\n```js\nvar swaggerValidator = require('swagger-object-validator');\nvar validator = new swaggerValidator.Handler('https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v2.0/yaml/petstore.yaml');\n\nvar pet = {\n    id: 123,\n    name: 'Doge'\n};\nvalidator.validateModel(pet, 'Pet', function (err, result) {\n    console.log(result.humanReadable());\n});\n```\n\nBoth will print out \"Valid\", since they comply to the swagger specification.\n\n## Error Trace\nSo lets change our pet model to be invalid (the rest of the code remains the same):\n```js\nvar pet = {\n    id: 'This is not a number',\n    foo: 'bar',\n    tag: [\n        'This is an optional argument, but it',\n        'Should be a String, not an Array of Strings'\n    ]\n}\n```\n\nNow it will print out:\n```\nMissing required property:\n\t - At Pet/name\n\nType mismatch:\n\t - At Pet/id\n\t - Should be: \"number\"\n\t - Is: \"string\"\n\nAdditional Property:\n\t - At Pet/foo\n\nType mismatch:\n\t - At Pet/tag\n\t - Should be: \"string\"\n\t - Is: \"array\"\n```\n\nThis is the **human readable** error trace, because we called `result.humanReadable()`. It will print out a full path to the error, where each step is seperated with a slash. They come quite handy if you need to find an error in a very complex model, and they support array positions and polymorphism!\n\nThe human readable trace is just a rendered version of `result.errors`, which looks like this:\n```json\n[\n    {\n        \"errorType\": \"MISSING_REQUIRED_PROPERTY\",\n        \"trace\": [\n            {\n                \"stepName\": \"Pet\"\n            },\n            {\n                \"stepName\": \"name\"\n            }\n        ]\n    },\n    {\n        \"errorType\": \"ADDITIONAL_PROPERTY\",\n        \"trace\": [\n            {\n                \"stepName\": \"Pet\"\n            },\n            {\n                \"stepName\": \"foo\"\n            }\n        ]\n    },\n    {\n        \"trace\": [\n            {\n                \"stepName\": \"Pet\"\n            },\n            {\n                \"stepName\": \"id\"\n            }\n        ],\n        \"errorType\": \"TYPE_MISMATCH\",\n        \"typeIs\": \"string\",\n        \"typeShouldBe\": \"number\"\n    },\n    {\n        \"trace\": [\n            {\n                \"stepName\": \"Pet\"\n            },\n            {\n                \"stepName\": \"tag\"\n            }\n        ],\n        \"errorType\": \"TYPE_MISMATCH\",\n        \"typeIs\": \"array\",\n        \"typeShouldBe\": \"string\"\n    }\n]\n```\n\n# Ways to load a specification\n## JSON/yaml/URL\nYou may load JSON or yaml files from your disk or from the interwebs. It doesn't matter!\n```Typescript\nimport * as SwaggerValidator from 'swagger-object-validator';\nlet validator = new SwaggerValidator.Handler('https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v2.0/yaml/petstore.yaml');\n// or\nlet validator = new SwaggerValidator.Handler('./petstore.yaml');\n// or\nlet validator = new SwaggerValidator.Handler('./petstore.json');\n// or\nlet petStore = require('./petstore.json');\nlet validator = new SwaggerValidator.Handler(petStore);\n```\n\n## Without an entire swagger spec\n\nUp to now we always loaded the complete Swagger Specification. Maybe you don't need that and already know the exact model spec? Just validate against a model spec directly:\n\n```ts\nimport * as SwaggerValidator from 'swagger-object-validator';\nlet validator = new SwaggerValidator.Handler();\n\nlet spec = {\n    type: \"array\",\n    items: {\n        type: \"string\"\n    }\n}\n\nlet model = ['1', '2'];\nvalidator.validateModel(model, spec, (err, result) =\u003e {\n    console.log(result.humanReadable());\n});\n```\n## Inline models / unnamed models\nIf you need to validate a model against a definition that is *not* part of the *definitions* section, you can fetch the model specification like so:\n\n```ts\nimport * as SwaggerValidator from 'swagger-object-validator';\nlet validator = new SwaggerValidator.Handler('https://raw.githubusercontent.com/YStrauch/swagger-object-validator/master/test/specs/yaml/swagger.yaml');\n\n// Fetch the unnamed model from i.e. a path\nlet schema = json.paths['/person'].post.parameters[0].schema\n\nvalidator.validateModel({'name': 'Homer'}, schema).then(result =\u003e {\n    console.log(result.humanReadable());\n});\n```\n\n# Config\nYou can hand in a configuration object. Before diving in each of them let's look over it quickly:\n```TypeScript\ninterface IValidatorConfig {\n  // for relative $refs, defaults to './'\n  partialsDir?: string;\n\n  // allow additional properties not defined in the Spec, defaults to false\n  allowAdditionalProperties?: boolean;\n\n  // allow usage of x-nullable for properties, defaults to false\n  allowXNullable?: boolean;\n\n  // will not check for uniqueItems constraint if there are more than this many, defaults to 100\n  disableUniqueItemsOver?: number;\n  // suppresses the console warning when uniqueItems was disabled due to disableUniqueItemsOver, defaults to false\n  suppressUniqueItemsWarning?: boolean;\n\n  // disallow fetching of HTTP and HTTPS resources, both default to false\n  disallowHttp?: boolean;\n  disallowHttps?: boolean;\n\n  // add custom validation rules (sync and async)\n  customValidation?: (\n    test: any,\n    schema: Swagger.Schema,\n    spec: Swagger.Spec,\n    trace: Array\u003cITraceStep\u003e,\n    otherErrors: Array\u003cICustomValidationError\u003e,\n    resolve?: (validationErrors: ICustomValidationError[]) =\u003e void,\n    reject?: (reason: string) =\u003e void\n  ) =\u003e ICustomValidationError[] | void | undefined;\n\n  // you can ignore certain errors\n  ignoreError?: ( // cb to ignore errors\n    error: IValidationError,\n    value: any,\n    schema: Swagger.Schema,\n    spec: Swagger.Spec\n  ) =\u003e boolean;\n}\n```\n\n## Partials directory for $ref\n$ref gives you the possibility to split your specification across different files (or even servers). There are multiple types of $refs:\n```yaml\n// internal $ref\n$ref: '#/definitions/Pet'\n\n// $ref to the interwebs\n$ref: 'https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v2.0/yaml/petstore.yaml#/definitions/Pet'\n\n// relative $ref\n$ref: './pet.json'\n```\nThe last kind of $refs, the relative ones, uses process.cwd() to determine the absolute path. If you want those $refs to resolve to another directory, you may specify a base path:\n\n```TypeScript\nlet config = {\n  partialsDir: '/some/path/'\n}\nlet validator = new SwaggerValidator.Handler('spec.yml', config);\n```\n\n## Disallowing HTTP or HTTPs\nAs described in the paragraph above Swagger allows references to the interwebs. If you do not want this you can set a corresponding option:\n```js\nlet config = {\n  disallowHttp: true,\n  disallowHttps: true\n};\nlet validator = new Handler('http://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v2.0/yaml/petstore.yaml', config);\n```\n\n## Allowing Additional properties\nBy default, every property that is not specified within the swagger definition adds an\nADDITIONAL_PROPERTY error to the stack. If you want to allow certain properties you can\ndo that with the ignoreError function (see \"Ignoring Errors\" below), or you can allow all additional properties at once with a config entry:\n\n```TypeScript\nlet config: IValidatorConfig = {\n    allowAdditionalProperties: true\n};\n```\n\n## Allowing `x-nullable` properties\nA common extension for Swagger 2 is `x-nullable`, based on\n[`nullable` from the OpenAPI 3 spec](https://swagger.io/specification/#schemaNullable).\nThis allows a property to be returned as `null` instead of the intended type.\n\nBy enabling this configuration, the `x-nullable` property is recognized and respected\nwhen validating types.\n\n```TypeScript\nlet config: IValidatorConfig = {\n    allowXNullable: true\n};\n```\n\n## Limiting the Unique Items Constraint\nSince version 1.4.0, this library implements the `uniqueItems` constraint. This constraint can be set on array specs to disallow duplicate items and emit a ConstraintViolation if needed.\n\nDetecting duplicate items needs to compare all items pairwise, and since items can be of arbitrary depth, this could bring drastic performance bottlenecks when you have a big number of items (or very complex items).\n\nTo prevent the validator to get stuck on this, by default it will never validate arrays for uniqueness that have more than 100 elements. You can change that cap with the `disableUniqueItemsOver` in your validator config to accommodate your needs and hardware.\n\nIf the cap is exceeded, a console warning will be emitted by default. You can disable this warning by setting `suppressUniqueItemsWarning` to true in your validator config.\n\nFor example, if you want to validate unique lists of up to 300 elements, you can change the cap and disable warnings like so:\n\n```TypeScript\nlet config = {\n  disableUniqueItemsOver: 300,\n  suppressUniqueItemsWarning: true\n}\nlet validator = new SwaggerValidator.Handler('spec.yml', config);\n```\n\nJust remember that the algorithm will scale exponentially in the number of items.\n\n## Ignoring errors\nYou may want to ignore certain errors. Let's assume you need some magic to allow a certain\nstring to be valid on a field that should normally be a number (because of reasons):\n```TypeScript\nlet config: IValidatorConfig = {\n    ignoreError: (error, value, schema, spec) =\u003e {\n      // ignore type mismatches on Pet/id when a certain value occures\n      return error.errorType === ValidationErrorType.TYPE_MISMATCH\n        \u0026\u0026 error.trace[0].stepName === 'Pet'\n        \u0026\u0026 error.trace[1].stepName === 'id'\n        \u0026\u0026 schema.type === 'integer'\n        \u0026\u0026 value === 'magicKeyThatWillBeAllowed';\n    }\n};\nlet validator = new Handler('https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v2.0/yaml/petstore.yaml', config);\nlet pet = {\n  id: 'magicKeyThatWillBeAllowed',\n  name: 'Doge'\n};\nvalidator.validateModel(pet, 'Pet', (err, result) =\u003e {\n  console.log(result.humanReadable()); // valid\n```\n\n## Custom validation rules\nYou may need to implement custom rules, for example you may want to ensure that a pet name always starts with an uppercase letter.\n*(For that specific use case you should probably just use a \"pattern\" regex swagger rule but for the sake of documentation we forget about this)*\n```TypeScript\nlet config: IValidatorConfig = {\n    customValidation: (test, schema, spec, trace, otherErrors) =\u003e {\n      // only validate Pet/name\n      if (trace.length !== 2\n        || trace[trace.length - 2].stepName !== 'Pet'\n        || trace[trace.length - 1].stepName !== 'name') {\n        // the property is not a pet name, so do not return any validation errors\n        return [];\n      }\n\n      // no need to ensure that petName is actually a string, because this will be already done for you\n      let firstChar = test.substr(0,1);\n      if (firstChar !== firstChar.toUpperCase()) {\n        return [\n          // You may throw a custom error, where content is any type\n          {\n            errorType: ValidationErrorType.CUSTOM, // or 6 for JS\n            trace: trace,\n            content: 'Name must start with an uppercase letter'\n          }\n        ];\n      }\n\n      // pet starts with an uppercase, so do not return validation errors\n      return [];\n    }\n  };\n```\n\nYou may either return an array of errors, or if you need to do asynchronously magic, you can use the resolve callback (or the reject callback to throw a critical error). Make sure not to mix return and resolve though.\n```TypeScript\ncustomValidation: (test, schema, spec, trace, otherErrors, resolve, reject) =\u003e {\n  setTimeout(() =\u003e resolve([]), 100);\n}\n```\n\n***Important:***\n- Swagger-Object-Validator will run its validation logic before your custom validation is called.\nIf any validation error occur within that logic, your handler is **not** called.\n(Would be annoying if we had to check if the name is a string right?)\n- With great power comes great runtime exceptions. If you allow for example a string on\nan object field to pass, the Object validator will crash because it expects\nits input to be an object. This hook should be used with caution.\n- Normally you should not need to implement custom rules, because you will add constraints that are not specified within the specification. Think first if you may be better on with a regex experssion, a min/max or any other swagger constraint.\n\n# Polymorphism\nSwagger-Object-Validator can work with two types of polymorphism.\n\n## Standard polymorphism\nMedium is a superclass of Image and Video. The discriminator _type_ can either be \"Image\" or \"Video\".\nThis is the way swagger intended polymorphism.\n```yaml\nMedium:\n  required:\n    - type\n  properties:\n    type:\n      type: string\nImage:\n    required:\n      - source\n    allOf:\n      - $ref: '#/definitions/Medium'\n    properties:\n      source:\n        type: string\nVideo:\n    required:\n      - length\n    allOf:\n      - $ref: '#/definitions/Medium'\n    properties:\n      length:\n        type: integer\n```\n\n```TypeScript\nlet medium = {\n  type: 'Image',\n  source: 'source' // property only exists within image\n};\n\n// the plot in polymorphism is that you validate\n// your model against the abstract Medium class,\n// not against the concrete Image class\nvalidator.validateModel(medium, 'Medium', (err, result) =\u003e {\n  //...\n});\n```\n\n## Enum polymorphism\nInstead of using the Name of the object, enum polymorphism uses enums to differentiate:\n\n```yaml\nSection:\n  required:\n    - sectionType\n  discriminator: sectionType\n  properties:\n    sectionType:\n      type: string\n      enum:\n        - TEXT_SECTION\n        - IMAGE_SECTION\n\nTextSection:\n  allOf:\n    - $ref: '#/definitions/Section'\n  properties:\n    sectionType:\n      type: string\n      enum:\n        - TEXT_SECTION\n    textContent:\n      type: string\n\nImageSection:\n  required:\n    - imageSource\n  allOf:\n    - $ref: '#/definitions/Section'\n  properties:\n    sectionType:\n      type: string\n      enum:\n        - IMAGE_SECTION\n    imageSource:\n      type: string\n```\n```TypeScript\nlet section = {\n  sectionType: 'TEXT_SECTION',\n  textContent: 'Custom polymorphed text section'\n};\n```\n\n## Polymorphism within the stack trace\nThe stack trace will tell you if polymorphism was detected.\nSo if a Medium may be an Image, and Polymorphism was detected, a trace may look like this:\n\n```json\n{\n    \"errors\": [\n        {\n            \"errorType\": \"MISSING_REQUIRED_PROPERTY\",\n            \"trace\": [\n                {\n                    \"stepName\": \"Medium\",\n                    \"concreteModel\": \"Image\" // here\n                },\n                {\n                    \"stepName\": \"source\"\n                }\n            ]\n        }\n    ]\n}\n```\n\nHumanReadable:\n```\nMissing required property:\n\t - At Medium\u003cImage\u003e/source\n```\n\n# Potentially breaking Changes\n## 1.3.0\n- Fixed typo, changed `ValidationErrorType` from 'CONSTRAINTS_VIOATION' to 'CONSTRAINTS_VIOLATION' (added missing L)\n- If you call `validateModel()` without a full-fledged spec (i.e. just the model definition), the first error step did previously not have a name. This was changed to the dedicated name 'root'.\n\n## 1.4.0\n- The `ValidationErrorType` in `result.model` was changed from a numeric enum to a more verbose string enum. This will mainly affect JavaScript applications and their logic to handle specific validation errors. TypeScript applications should be unaffected if the enums were used as documented. The values changed from integers between 0 and 6 to 'MISSING_REQUIRED_PROPERTY', 'ADDITIONAL_PROPERTY', 'TYPE_MISMATCH', 'ENUM_MISMATCH', 'DATE_FORMAT', 'CONSTRAINTS_VIOLATION', and 'CUSTOM'. This deprecated `errorsWithStringTypes`.\n- Added support for `uniqueItems`. Please also read about the default cap of 100 items [here](#Limiting-the-Unique-Items-Constraint).\n\n# Development\n\n## Technical Setup\nInstall node.js. Then run: `npm install --global yarn; yarn install`.\nPlease make sure to use an IDE with TSLint and EditorConfig installed (i.e. Visual Studio Code).\n\n## Development\nThis project is entirely test-driven. You can run tests locally like this:\n\n```bash\nnpm run-script watch:test # Build the application, run tests and watch the FS\nnpm run-script debug # Very useful to trace bugs. You need a remote debugging software, I use VSCode debugger\n```\n\nTests need to have **minimum** code to test the desired effect. Don't include huge swagger specs.\n\n## Pull-Requests\nPlease ensure that your pull request includes tests that demonstrate the feature or bug fix and that your code conforms to the TSLint specifications in this project.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fystrauch%2Fswagger-object-validator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fystrauch%2Fswagger-object-validator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fystrauch%2Fswagger-object-validator/lists"}