{"id":13528366,"url":"https://github.com/epiphone/class-validator-jsonschema","last_synced_at":"2025-05-16T11:04:34.491Z","repository":{"id":38290855,"uuid":"112473994","full_name":"epiphone/class-validator-jsonschema","owner":"epiphone","description":"Convert class-validator-decorated classes into JSON schema","archived":false,"fork":false,"pushed_at":"2025-03-04T01:18:01.000Z","size":660,"stargazers_count":231,"open_issues_count":30,"forks_count":36,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-05-13T07:41:59.350Z","etag":null,"topics":["api-documentation","api-documentation-tool","json-schema","openapi3","typescript-validation","validation"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/epiphone.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-11-29T12:41:25.000Z","updated_at":"2025-05-09T13:05:53.000Z","dependencies_parsed_at":"2024-01-13T22:23:18.655Z","dependency_job_id":"588ff741-e648-4627-a9a9-99d0ccc0216e","html_url":"https://github.com/epiphone/class-validator-jsonschema","commit_stats":{"total_commits":117,"total_committers":15,"mean_commits":7.8,"dds":0.5811965811965811,"last_synced_commit":"4821a25a4224dd7c8f6e08fe2370235f9d8bf1f7"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epiphone%2Fclass-validator-jsonschema","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epiphone%2Fclass-validator-jsonschema/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epiphone%2Fclass-validator-jsonschema/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/epiphone%2Fclass-validator-jsonschema/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/epiphone","download_url":"https://codeload.github.com/epiphone/class-validator-jsonschema/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254110374,"owners_count":22016391,"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":["api-documentation","api-documentation-tool","json-schema","openapi3","typescript-validation","validation"],"created_at":"2024-08-01T06:02:28.205Z","updated_at":"2025-05-16T11:04:34.323Z","avatar_url":"https://github.com/epiphone.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","others"],"sub_categories":[],"readme":"# class-validator-jsonschema\n\n[![npm version](https://badge.fury.io/js/class-validator-jsonschema.svg)](https://badge.fury.io/js/class-validator-jsonschema)\n\nConvert [class-validator](https://github.com/typestack/class-validator)-decorated classes into OpenAPI-compatible JSON Schema. The aim is to provide a best-effort conversion: since some of the `class-validator` decorators lack a direct JSON Schema counterpart, the conversion is bound to be somewhat opinionated. To account for this multiple extension points are available.\n\n## Installation\n\n`npm install class-validator-jsonschema`\n\n**Note the peer dependency versions** in [package.json](./package.json). Try installing a previous major version of `class-validator-jsonschema` in case you're stuck with older peer dependencies.\n\n## Usage\n\n```typescript\nimport { IsOptional, IsString, MaxLength } from 'class-validator'\nimport { validationMetadatasToSchemas } from 'class-validator-jsonschema'\n\nclass BlogPost {\n  @IsString() id: string\n\n  @IsOptional()\n  @MaxLength(20, { each: true })\n  tags: string[]\n}\n\nconst schemas = validationMetadatasToSchemas()\nconsole.log(schemas)\n```\n\nwhich prints out:\n\n```json\n{\n  \"BlogPost\": {\n    \"properties\": {\n      \"id\": {\n        \"type\": \"string\"\n      },\n      \"tags\": {\n        \"items\": {\n          \"maxLength\": 20,\n          \"type\": \"string\"\n        },\n        \"type\": \"array\"\n      }\n    },\n    \"required\": [\"id\"],\n    \"type\": \"object\"\n  }\n}\n```\n\n`validationMetadatasToSchemas` takes an `options` object as an optional parameter. Check available configuration objects and defaults at [`options.ts`](src/options.ts).\n\n### Adding and overriding default converters\n\nWith `options.additionalConverters` you can add new validation metadata converters or override [the existing ones](src/defaultConverters.ts). Let's say we want to, for example, add a handy `description` field to each `@IsString()`-decorated property:\n\n```typescript\nimport { ValidationTypes } from 'class-validator'\n\n// ...\n\nconst schemas = validationMetadatasToSchemas({\n  additionalConverters: {\n    [ValidationTypes.IS_STRING]: {\n      description: 'A string value',\n      type: 'string',\n    },\n  },\n})\n```\n\nwhich now outputs:\n\n```json\n{\n  \"BlogPost\": {\n    \"properties\": {\n      \"id\": {\n        \"description\": \"A string value\",\n        \"type\": \"string\"\n      }\n      // ...\n    }\n  }\n}\n```\n\nAn additional converter can also be supplied in form of a function that receives the validation metadata item and global options, outputting a JSON Schema property object (see below for usage):\n\n```typescript\ntype SchemaConverter = (\n  meta: ValidationMetadata,\n  options: IOptions\n) =\u003e SchemaObject | void\n```\n\n### Custom validation classes\n\n`class-validator` allows you to define [custom validation classes](https://github.com/typestack/class-validator#custom-validation-classes). You might for example validate that a string's length is between given two values:\n\n```typescript\nimport {\n  Validate,\n  ValidationArguments,\n  ValidatorConstraint,\n  ValidatorConstraintInterface,\n} from 'class-validator'\n\n// Implementing the validator:\n\n@ValidatorConstraint()\nexport class CustomTextLength implements ValidatorConstraintInterface {\n  validate(text: string, validationArguments: ValidationArguments) {\n    const [min, max] = validationArguments.constraints\n    return text.length \u003e= min \u0026\u0026 text.length \u003c= max\n  }\n}\n\n// ...and putting it to use:\n\nclass Post {\n  @Validate(CustomTextLength, [0, 11])\n  title: string\n}\n```\n\nNow to handle your custom validator's JSON Schema conversion include a `CustomTextLength` converter in `options.additionalConverters`:\n\n```typescript\nconst schemas = validationMetadatasToSchemas({\n  additionalConverters: {\n    CustomTextLength: (meta) =\u003e ({\n      maxLength: meta.constraints[1],\n      minLength: meta.constraints[0],\n      type: 'string',\n    }),\n  },\n})\n```\n\n### Decorating with additional properties\n\nValidation classes can also be supplemented with the `JSONSchema` decorator. `JSONSchema` can be applied both to classes and individual properties; any given keywords are then [merged](https://lodash.com/docs/4.17.4#merge) into the JSON Schema derived from class-validator decorators:\n\n```typescript\nimport { JSONSchema } from 'class-validator-jsonschema'\n\n@JSONSchema({\n  description: 'A User object',\n  example: { id: '123' },\n})\nclass BlogPost {\n  @IsString()\n  @JSONSchema({\n    description: 'User primary key',\n    format: 'custom-id',\n  })\n  id: string\n}\n```\n\nResults in the following schema:\n\n```json\n{\n  \"BlogPost\": {\n    \"description\": \"A User object\",\n    \"example\": { \"id\": \"123\" },\n    \"properties\": {\n      \"id\": {\n        \"description\": \"User primary key\",\n        \"format\": \"custom-id\",\n        \"type\": \"string\"\n      }\n    },\n    \"required\": [\"id\"],\n    \"type\": \"object\"\n  }\n}\n```\n\n`JSONSchema` decorators also flow down from parent classes into [inherited validation decorators](https://github.com/typestack/class-validator#inheriting-validation-decorators). Note though that if the inherited class uses `JSONSchema` to redecorate a property from the parent class, the parent class `JSONSchema` gets overwritten - i.e. there's no merging logic.\n\n#### Custom handlers\n\nAlternatively `JSONSchema` can take a function of type `(existingSchema: SchemaObject, options: IOptions) =\u003e SchemaObject`. The return value of this function is then **not** automatically merged into existing schema (i.e. the one derived from `class-validator` decorators). Instead you can handle merging yourself in whichever way is preferred, the idea being that removal of existing keywords and other more complex overwrite scenarios can be implemented here.\n\n### @ValidateNested and arrays\n\n`class-validator` supports validating nested objects via the [`@ValidateNested` decorator](https://github.com/typestack/class-validator#validating-nested-objects). Likewise JSON Schema generation is supported out-of-the-box for nested properties such as\n\n```typescript\n@ValidateNested()\nuser: UserClass\n```\n\nHowever, due to [limitations in Typescript's reflection system](https://github.com/Microsoft/TypeScript/issues/10576) we cannot infer the inner type of a generic class. In effect this means that properties like\n\n```typescript\n@ValidateNested({ each: true })\nusers: UserClass[]\n\n@ValidateNested()\nuser: Promise\u003cUserClass\u003e\n```\n\nwould resolve to classes `Array` and `Promise` in JSON Schema. To work around this limitation we can use `@Type` from `class-transformer` to explicitly define the nested property's inner type:\n\n```typescript\nimport { Type } from 'class-transformer'\nimport { validationMetadatasToSchemas } from 'class-validator-jsonschema'\nconst { defaultMetadataStorage } = require('class-transformer/cjs/storage') // See https://github.com/typestack/class-transformer/issues/563 for alternatives\n\nclass User {\n  @ValidateNested({ each: true })\n  @Type(() =\u003e BlogPost) // 1) Explicitly define the nested property type\n  blogPosts: BlogPost[]\n}\n\nconst schemas = validationMetadatasToSchemas({\n  classTransformerMetadataStorage: defaultMetadataStorage, // 2) Define class-transformer metadata in options\n})\n```\n\nNote also how the `classTransformerMetadataStorage` option has to be defined for `@Type` decorator to take effect.\n\n### Using a custom validation metadataStorage\n\nUnder the hood we grab validation metadata from the default storage returned by `class-validator`'s `getMetadataStorage()`. In case of a version clash or something you might want to manually pass in the storage:\n\n```typescript\nconst schemas = validationMetadatasToSchemas({\n  classValidatorMetadataStorage: myCustomMetadataStorage,\n})\n```\n\n## Limitations\n\nThere's no handling for `class-validator`s **validation groups** or **conditional decorator** (`@ValidateIf`) out-of-the-box. The above-mentioned extension methods can be used to fill the gaps if necessary.\n\nThe OpenAPI spec doesn't currently support the new JSON Schema **draft-06 keywords** `const` and `contains`. This means that constant value decorators such as `@IsEqual()` and `@ArrayContains()` translate to quite [complicated schemas](https://github.com/sahava/gtm-datalayer-test/issues/4). Hopefully [in a not too distant future](https://github.com/OAI/OpenAPI-Specification/issues/1313#issuecomment-335893062) these keywords are adopted into the spec and we'll be able to provide neater conversion.\n\nHandling **null values** is also tricky since OpenAPI doesn't support JSON Schema's `type: null`, providing its own `nullable` keyword instead. The default `@IsEmpty()` converter for example opts for `nullable` but you can use `type: null` instead via `options.additionalConverters`:\n\n```typescript\n// ...\nadditionalConverters: {\n  [ValidationTypes.IS_EMPTY]: {\n    anyOf: [\n      {type: 'string', enum: ['']},\n      {type: 'null'}\n    ]\n  }\n}\n```\n\n## TODO\n\n- [x] handle `skipMissingProperties` and `@isDefined()`\n- [x] decorators for overwriting prop schemas\n- [ ] optional property descriptions (e.g. `A Base64-encoded string`)\n- [ ] optional draft-06 keywords\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fepiphone%2Fclass-validator-jsonschema","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fepiphone%2Fclass-validator-jsonschema","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fepiphone%2Fclass-validator-jsonschema/lists"}