{"id":15102815,"url":"https://github.com/nullpub/jsonschema","last_synced_at":"2025-09-27T00:31:40.545Z","repository":{"id":62421802,"uuid":"317992169","full_name":"nullpub/jsonschema","owner":"nullpub","description":"Generate JsonSchema and TypeScript types at the same time","archived":true,"fork":false,"pushed_at":"2021-10-06T22:28:21.000Z","size":28,"stargazers_count":9,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-09-21T08:03:09.920Z","etag":null,"topics":["deno","jsonschema","typescript-types"],"latest_commit_sha":null,"homepage":"https://deno.land/x/jsonschema","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/nullpub.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2020-12-02T21:10:01.000Z","updated_at":"2023-01-28T06:06:22.000Z","dependencies_parsed_at":"2022-11-01T17:31:47.941Z","dependency_job_id":null,"html_url":"https://github.com/nullpub/jsonschema","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nullpub%2Fjsonschema","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nullpub%2Fjsonschema/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nullpub%2Fjsonschema/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nullpub%2Fjsonschema/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nullpub","download_url":"https://codeload.github.com/nullpub/jsonschema/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219871828,"owners_count":16554457,"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":["deno","jsonschema","typescript-types"],"created_at":"2024-09-25T19:07:26.230Z","updated_at":"2025-09-27T00:31:35.265Z","avatar_url":"https://github.com/nullpub.png","language":"TypeScript","readme":"# This Library is now hosted directly in [functional](https://github.com/nullpub/fun/blob/main/schemable/json.ts). For the latest version look there.\n\n# JsonSchema for Deno [![Coverage Status](https://coveralls.io/repos/github/nullpub/jsonschema/badge.svg?branch=main)](https://coveralls.io/github/nullpub/jsonschema?branch=main)\n\nA library for constructing JsonSchemas and TypeScript types simultaneously.\n\n## Usage\n\nThis library is a collection of combinators that can be used to construct\njson schemas and their associated TypeScript types at the same time. It follows\nthe pattern laid down by gcanti in io-ts. Following is the simple usage case:\n\n```ts\nimport * as J from \"https://deno.land/x/jsonschema/jsonschema.ts\";\n\n/**\n * Declare the type using json_schema combinators\n */\nconst MyType = J.type({\n  foo: J.partial({\n    bar: J.array(J.literal(1, 2)),\n  }),\n});\n\n/**\n * Derive the TypeScript from the JsonSchema instance\n * Equivalent to:\n *\n * type MyType = {\n *   foo: Partial\u003c{\n *     bar: readonly (1 | 2)[];\n *   }\u003e;\n * }\n */\ntype MyType = J.TypeOf\u003ctypeof MyType\u003e;\n\n/**\n * Print the stringified json schema\n * Equivalent to:\n *\n * {\n *   \"definitions\": {},\n *   \"properties\": {\n *     \"foo\": {\n *       \"properties\": {\n *         \"bar\": {\n *           \"items\": {\n *             \"enum\": [\n *               1,\n *               2\n *             ]\n *           },\n *           \"type\": \"array\"\n *         }\n *       },\n *       \"type\": \"object\"\n *     }\n *   },\n *   \"required\": [\n *     \"foo\"\n *   ],\n *   \"type\": \"object\"\n * }\n */\nconsole.log(JSON.stringify(J.print(MyType)));\n```\n\nThere is also an export of a Schemable for use with [fun](https://deno.land/x/fun).\nIf you use the functional Schemable `make` function to create a `Schemable` you can use\nthat to generate a jsonschema as well.\n\n```ts\nimport * as J from \"https://deno.land/x/jsonschema/jsonschema.ts\";\nimport * as S from \"https://deno.land/x/fun@v1.0.0/schemable/schemable.ts\";\n\n/**\n * Declare the type using schemable combinators\n */\nconst MyType = S.make((s) =\u003e\n  s.type({\n    foo: s.partial({\n      bar: s.array(s.literal(1, 2)),\n    }),\n  })\n);\n\n/**\n * Derive the TypeScript from the Schemable instance\n * Equivalent to:\n *\n * type MyType = {\n *   foo: Partial\u003c{\n *     bar: readonly (1 | 2)[];\n *   }\u003e;\n * }\n */\ntype MyType = S.TypeOf\u003ctypeof MyType\u003e;\n\n/**\n * Generate the JsonSchema from the Schemable\n */\nconst MyTypeJsonSchema = MyType(J.Schemable);\n\n/**\n * Print the strigified json schema\n * Equivalent to:\n *\n * {\n *   \"definitions\": {},\n *   \"properties\": {\n *     \"foo\": {\n *       \"properties\": {\n *         \"bar\": {\n *           \"items\": {\n *             \"enum\": [\n *               1,\n *               2\n *             ]\n *           },\n *           \"type\": \"array\"\n *         }\n *       },\n *       \"type\": \"object\"\n *     }\n *   },\n *   \"required\": [\n *     \"foo\"\n *   ],\n *   \"type\": \"object\"\n * }\n */\nconsole.log(JSON.stringify(J.print(MyTypeJsonSchema), null, 2));\n```\n\nAs you can see, there is very little difference. The benefit is that\na `Schemable` can also be used to generate a fun [decoder](https://deno.land/x/fun/schemabledecoder.ts).\n\nLastly, this library properly handles recursive types/schemas with the `lazy` combinator. Unfortunately,\nthe recursive type must be defined as a typescript type since type inference can't name recursive types for you.\n\n```ts\nimport * as J from \"https://deno.land/x/jsonschema/jsonschema.ts\";\n\ntype Foo = {\n  foo?: Foo;\n  bar: string;\n};\n\nconst Foo: J.JsonSchema\u003cFoo\u003e = J.lazy(\"Foo\", () =\u003e\n  J.intersect(J.partial({ foo: Foo }), J.type({ bar: J.string }))\n);\n\nconsole.log(JSON.stringify(J.print(Foo), null, 2));\n// Prints\n// {\n//   \"$ref\": \"#/definitions/Foo\",\n//   \"definitions\": {\n//     \"Foo\": {\n//       \"allOf\": [\n//         {\n//           \"properties\": {\n//             \"foo\": {\n//               \"$ref\": \"#/definitions/Foo\"\n//             }\n//           },\n//           \"type\": \"object\"\n//         },\n//         {\n//           \"properties\": {\n//             \"bar\": {\n//               \"type\": \"string\"\n//             }\n//           },\n//           \"required\": [\n//             \"bar\"\n//           ],\n//           \"type\": \"object\"\n//         }\n//       ]\n//     }\n//   }\n// }\n```\n\nAdditionally, mutual recursion is also possible:\n\n```ts\nimport * as J from \"https://deno.land/x/jsonschema/jsonschema.ts\";\n\nconst Bar = J.lazy(\"Bar\", () =\u003e\n  J.type({\n    foo: Foo,\n  })\n);\ntype Bar = J.TypeOf\u003ctypeof Bar\u003e;\n\ntype Foo = {\n  bar: Bar[];\n  baz: string;\n};\n\nconst Foo: J.JsonSchema\u003cFoo\u003e = J.lazy(\"Foo\", () =\u003e\n  J.type({\n    bar: J.array(Bar),\n    baz: J.string,\n  })\n);\n\nconsole.log(JSON.stringify(J.print(Foo), null, 2));\n// {\n//   \"$ref\": \"#/definitions/Foo\",\n//   \"definitions\": {\n//     \"Foo\": {\n//       \"properties\": {\n//         \"bar\": {\n//           \"items\": {\n//             \"$ref\": \"#/definitions/Bar\"\n//           },\n//           \"type\": \"array\"\n//         },\n//         \"baz\": {\n//           \"type\": \"string\"\n//         }\n//       },\n//       \"required\": [\n//         \"bar\",\n//         \"baz\"\n//       ],\n//       \"type\": \"object\"\n//     },\n//     \"Bar\": {\n//       \"properties\": {\n//         \"foo\": {\n//           \"$ref\": \"#/definitions/Foo\"\n//         }\n//       },\n//       \"required\": [\n//         \"foo\"\n//       ],\n//       \"type\": \"object\"\n//     }\n//   }\n// }\n```\n\n## Api\n\n### Types\n\n| Type                                 | Notes                                                                                      |\n| ------------------------------------ | ------------------------------------------------------------------------------------------ |\n| `JsonSchema\u003cA\u003e`                      | An alias of the `State` Monad that evaluates to a `[Json.Type, Json.Definitions]`          |\n| `TypeOf\u003cT\u003e`                          | A type extraction tool used to get the TypeScript type representation of a `JsonSchema\u003cA\u003e` |\n| `import * as Json from \"./types.ts\"` | Partial TypeScript type implementations of actual Json Schema                              |\n\n### Combinators\n\n| Combinator | Description                                                                                                                   | Example                                                                |\n| ---------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |\n| nullable   | Takes in a `JsonSchema\u003cA\u003e` and returns a `JsonSchema` of the union `A and null`                                               | `J.nullable(J.string)`                                                 |\n| literal    | Takes in a variadic number of `Primitive` values and a union of those literals                                                | `J.literal(1, 2, 3, \"a\", \"b\", \"c\")`                                    |\n| string     | Returns a `JsonSchema\u003cstring\u003e`                                                                                                | `J.string`                                                             |\n| number     | Returns a `JsonSchema\u003cnumber\u003e`                                                                                                | `J.number`                                                             |\n| boolean    | Returns a `JsonSchema\u003cboolean\u003e`                                                                                               | `J.boolean`                                                            |\n| type       | Takes in a `Record\u003cstring, JsonSchema\u003cany\u003e` and returns a JsonSchema `object` with the same shape with all fields required    | `J.type({ foo: J.string, bar: J.number })`                             |\n| partial    | Takes in a `Record\u003cstring, JsonSchema\u003cany\u003e` and returns a JsonSchema `object` with the same shape                             | `J.partial({ foo: J.string, bar: J.number })`                          |\n| array      | Takes in a `JsonSchema\u003cA\u003e` and returns a `JsonSchema\u003cArray\u003cA\u003e\u003e`                                                               | `J.array(J.string)`                                                    |\n| record     | Takes in a `JsonSchema\u003cA\u003e` and returns a `JsonSchema\u003cRecord\u003cstring, A\u003e\u003e`                                                      | `J.record(J.string)`                                                   |\n| tuple      | Takes in a variadic number of args like `JsonSchema\u003cstring\u003e, JsonSchema\u003cnumber\u003e` and returns a `JsonSchema\u003c[string, number]\u003e` | `J.tuple(J.string, J.number)`                                          |\n| union      | Takes in a variadic number of and returns thier union                                                                         | `J.union(J.number, J.string)`                                          |\n| intersect  | Takes in exactly two schemas and returns their intersection                                                                   | `J.intersect(J.partial({ foo: J.number }), J.type({ bar: J.string }))` |\n| sum        | Takes in a tag and a record of `JsonSchema` that each contain a key with tag as the name and returns a union of the members   | `J.sum('myTag', { foo: J.type({ myTag: J.literal('foo') })})`          |\n| lazy       | Takes in a key and a function that returns a JsonSchema and returs a Json Schema `$ref`                                       | `J.lazy('Foo', () =\u003e J.type({ foo: J.string }))`                       |\n| print      | Takes in a `JsonSchema\u003cA\u003e` and returns the actual Json Schema representation                                                  | `J.print(J.string)`                                                    |\n\n### Modules\n\n`Schemable` is a type from [fun schemable](https://deno.land/x/fun/schemable/schemable.ts) that abstracts the combinator pattern used in `jsonschema.ts`. Effectively, instead of using jsonschema.ts combinators directly, one can define a `Schemable` instance using the `make` function from `hkts schemable` and then derive the actual json schema from that.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnullpub%2Fjsonschema","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnullpub%2Fjsonschema","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnullpub%2Fjsonschema/lists"}