{"id":13542528,"url":"https://github.com/invopop/jsonschema","last_synced_at":"2026-03-27T02:43:39.130Z","repository":{"id":39442897,"uuid":"458653303","full_name":"invopop/jsonschema","owner":"invopop","description":"Generate JSON Schemas from Go types","archived":false,"fork":false,"pushed_at":"2024-12-31T18:24:41.000Z","size":258,"stargazers_count":906,"open_issues_count":63,"forks_count":128,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-02-21T04:00:13.584Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","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/invopop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","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":"2022-02-12T22:22:58.000Z","updated_at":"2026-02-16T02:14:52.000Z","dependencies_parsed_at":"2023-09-26T18:31:17.663Z","dependency_job_id":"abe7328b-4761-487d-8fd9-a559aabe296b","html_url":"https://github.com/invopop/jsonschema","commit_stats":{"total_commits":185,"total_committers":57,"mean_commits":3.245614035087719,"dds":0.7351351351351352,"last_synced_commit":"a4467074499db5797e8aa5c6da052c69bbba9127"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/invopop/jsonschema","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/invopop%2Fjsonschema","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/invopop%2Fjsonschema/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/invopop%2Fjsonschema/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/invopop%2Fjsonschema/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/invopop","download_url":"https://codeload.github.com/invopop/jsonschema/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/invopop%2Fjsonschema/sbom","scorecard":{"id":492362,"data":{"date":"2025-08-11","repo":{"name":"github.com/invopop/jsonschema","commit":"328cc73c3399c73df18b708fa00d29669cb0e4cc"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.5,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":6,"reason":"Found 8/12 approved changesets -- score normalized to 6","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/lint.yaml:1","Warn: no topLevel permission defined: .github/workflows/release.yaml:1","Warn: no topLevel permission defined: .github/workflows/test.yaml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint.yaml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/invopop/jsonschema/lint.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint.yaml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/invopop/jsonschema/lint.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/lint.yaml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/invopop/jsonschema/lint.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yaml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/invopop/jsonschema/release.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yaml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/invopop/jsonschema/release.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yaml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/invopop/jsonschema/test.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yaml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/invopop/jsonschema/test.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yaml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/invopop/jsonschema/test.yaml/main?enable=pin","Info:   0 out of   5 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: COPYING:0","Info: FSF or OSI recognized license: MIT License: COPYING:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":5,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'main'","Info: 'force pushes' disabled on branch 'main'","Warn: 'branch protection settings apply to administrators' is disabled on branch 'main'","Warn: 'stale review dismissal' is disabled on branch 'main'","Warn: required approving review count is 1 on branch 'main'","Warn: codeowners review is required - but no codeowners file found in repo","Warn: 'last push approval' is disabled on branch 'main'","Warn: no status checks found to merge onto branch 'main'","Info: PRs are required in order to make changes on branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":1,"reason":"SAST tool is not run on all commits -- score normalized to 1","details":["Warn: 5 commits out of 28 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-19T19:30:38.207Z","repository_id":39442897,"created_at":"2025-08-19T19:30:38.211Z","updated_at":"2025-08-19T19:30:38.211Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31011706,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-27T02:33:22.146Z","status":"ssl_error","status_checked_at":"2026-03-27T02:33:21.763Z","response_time":164,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2024-08-01T10:01:09.664Z","updated_at":"2026-03-27T02:43:39.096Z","avatar_url":"https://github.com/invopop.png","language":"Go","funding_links":[],"categories":["Go","others"],"sub_categories":[],"readme":"# Go JSON Schema Reflection\n\n[![Lint](https://github.com/invopop/jsonschema/actions/workflows/lint.yaml/badge.svg)](https://github.com/invopop/jsonschema/actions/workflows/lint.yaml)\n[![Test Go](https://github.com/invopop/jsonschema/actions/workflows/test.yaml/badge.svg)](https://github.com/invopop/jsonschema/actions/workflows/test.yaml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/invopop/jsonschema)](https://goreportcard.com/report/github.com/invopop/jsonschema)\n[![GoDoc](https://godoc.org/github.com/invopop/jsonschema?status.svg)](https://godoc.org/github.com/invopop/jsonschema)\n[![codecov](https://codecov.io/gh/invopop/jsonschema/graph/badge.svg?token=JMEB8W8GNZ)](https://codecov.io/gh/invopop/jsonschema)\n![Latest Tag](https://img.shields.io/github/v/tag/invopop/jsonschema)\n\nThis package can be used to generate [JSON Schemas](http://json-schema.org/latest/json-schema-validation.html) from Go types through reflection.\n\n- Supports arbitrarily complex types, including `interface{}`, maps, slices, etc.\n- Supports json-schema features such as minLength, maxLength, pattern, format, etc.\n- Supports simple string and numeric enums.\n- Supports custom property fields via the `jsonschema_extras` struct tag.\n\nThis repository is a fork of the original [jsonschema](https://github.com/alecthomas/jsonschema) by [@alecthomas](https://github.com/alecthomas). At [Invopop](https://invopop.com) we use jsonschema as a cornerstone in our [GOBL library](https://github.com/invopop/gobl), and wanted to be able to continue building and adding features without taking up Alec's time. There have been a few significant changes that probably mean this version is a not compatible with with Alec's:\n\n- The original was stuck on the draft-04 version of JSON Schema, we've now moved to the latest JSON Schema Draft 2020-12.\n- Schema IDs are added automatically from the current Go package's URL in order to be unique, and can be disabled with the `Anonymous` option.\n- Support for the `FullyQualifyTypeName` option has been removed. If you have conflicts, you should use multiple schema files with different IDs, set the `DoNotReference` option to true to hide definitions completely, or add your own naming strategy using the `Namer` property.\n- Support for `yaml` tags and related options has been dropped for the sake of simplification. There were a [few inconsistencies](https://github.com/invopop/jsonschema/pull/21) around this that have now been fixed.\n\n## Versions\n\nThis project is still under v0 scheme, as per Go convention, breaking changes are likely. Please pin go modules to version tags or branches, and reach out if you think something can be improved.\n\nGo version \u003e= 1.18 is required as generics are now being used.\n\n## Example\n\nThe following Go type:\n\n```go\ntype TestUser struct {\n  ID            int                    `json:\"id\"`\n  Name          string                 `json:\"name\" jsonschema:\"title=the name,description=The name of a friend,example=joe,example=lucy,default=alex\"`\n  Friends       []int                  `json:\"friends,omitempty\" jsonschema_description:\"The list of IDs, omitted when empty\"`\n  Tags          map[string]interface{} `json:\"tags,omitempty\" jsonschema_extras:\"a=b,foo=bar,foo=bar1\"`\n  BirthDate     time.Time              `json:\"birth_date,omitempty\" jsonschema:\"oneof_required=date\"`\n  YearOfBirth   string                 `json:\"year_of_birth,omitempty\" jsonschema:\"oneof_required=year\"`\n  Metadata      interface{}            `json:\"metadata,omitempty\" jsonschema:\"oneof_type=string;array\"`\n  FavColor      string                 `json:\"fav_color,omitempty\" jsonschema:\"enum=red,enum=green,enum=blue\"`\n}\n```\n\nResults in following JSON Schema:\n\n```go\njsonschema.Reflect(\u0026TestUser{})\n```\n\n```json\n{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"$id\": \"https://github.com/invopop/jsonschema_test/test-user\",\n  \"$ref\": \"#/$defs/TestUser\",\n  \"$defs\": {\n    \"TestUser\": {\n      \"oneOf\": [\n        {\n          \"required\": [\"birth_date\"],\n          \"title\": \"date\"\n        },\n        {\n          \"required\": [\"year_of_birth\"],\n          \"title\": \"year\"\n        }\n      ],\n      \"properties\": {\n        \"id\": {\n          \"type\": \"integer\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"title\": \"the name\",\n          \"description\": \"The name of a friend\",\n          \"default\": \"alex\",\n          \"examples\": [\"joe\", \"lucy\"]\n        },\n        \"friends\": {\n          \"items\": {\n            \"type\": \"integer\"\n          },\n          \"type\": \"array\",\n          \"description\": \"The list of IDs, omitted when empty\"\n        },\n        \"tags\": {\n          \"type\": \"object\",\n          \"a\": \"b\",\n          \"foo\": [\"bar\", \"bar1\"]\n        },\n        \"birth_date\": {\n          \"type\": \"string\",\n          \"format\": \"date-time\"\n        },\n        \"year_of_birth\": {\n          \"type\": \"string\"\n        },\n        \"metadata\": {\n          \"oneOf\": [\n            {\n              \"type\": \"string\"\n            },\n            {\n              \"type\": \"array\"\n            }\n          ]\n        },\n        \"fav_color\": {\n          \"type\": \"string\",\n          \"enum\": [\"red\", \"green\", \"blue\"]\n        }\n      },\n      \"additionalProperties\": false,\n      \"type\": \"object\",\n      \"required\": [\"id\", \"name\"]\n    }\n  }\n}\n```\n\n## YAML\n\nSupport for `yaml` tags has now been removed. If you feel very strongly about this, we've opened a discussion to hear your comments: https://github.com/invopop/jsonschema/discussions/28\n\nThe recommended approach if you need to deal with YAML data is to first convert to JSON. The [invopop/yaml](https://github.com/invopop/yaml) library will make this trivial.\n\n## Configurable behaviour\n\nThe behaviour of the schema generator can be altered with parameters when a `jsonschema.Reflector`\ninstance is created.\n\n### ExpandedStruct\n\nIf set to `true`, makes the top level struct not to reference itself in the definitions. But type passed should be a struct type.\n\neg.\n\n```go\ntype GrandfatherType struct {\n\tFamilyName string `json:\"family_name\" jsonschema:\"required\"`\n}\n\ntype SomeBaseType struct {\n\tSomeBaseProperty int `json:\"some_base_property\"`\n\t// The jsonschema required tag is nonsensical for private and ignored properties.\n\t// Their presence here tests that the fields *will not* be required in the output\n\t// schema, even if they are tagged required.\n\tsomePrivateBaseProperty            string `json:\"i_am_private\" jsonschema:\"required\"`\n\tSomeIgnoredBaseProperty            string `json:\"-\" jsonschema:\"required\"`\n\tSomeSchemaIgnoredProperty          string `jsonschema:\"-,required\"`\n\tSomeUntaggedBaseProperty           bool   `jsonschema:\"required\"`\n\tsomeUnexportedUntaggedBaseProperty bool\n\tGrandfather                        GrandfatherType `json:\"grand\"`\n}\n```\n\nwill output:\n\n```json\n{\n  \"$schema\": \"http://json-schema.org/draft/2020-12/schema\",\n  \"required\": [\"some_base_property\", \"grand\", \"SomeUntaggedBaseProperty\"],\n  \"properties\": {\n    \"SomeUntaggedBaseProperty\": {\n      \"type\": \"boolean\"\n    },\n    \"grand\": {\n      \"$schema\": \"http://json-schema.org/draft/2020-12/schema\",\n      \"$ref\": \"#/definitions/GrandfatherType\"\n    },\n    \"some_base_property\": {\n      \"type\": \"integer\"\n    }\n  },\n  \"type\": \"object\",\n  \"$defs\": {\n    \"GrandfatherType\": {\n      \"required\": [\"family_name\"],\n      \"properties\": {\n        \"family_name\": {\n          \"type\": \"string\"\n        }\n      },\n      \"additionalProperties\": false,\n      \"type\": \"object\"\n    }\n  }\n}\n```\n\n### Using Go Comments\n\nWriting a good schema with descriptions inside tags can become cumbersome and tedious, especially if you already have some Go comments around your types and field definitions. If you'd like to take advantage of these existing comments, you can use the `AddGoComments(base, path string)` method that forms part of the reflector to parse your go files and automatically generate a dictionary of Go import paths, types, and fields, to individual comments. These will then be used automatically as description fields, and can be overridden with a manual definition if needed.\n\nTake a simplified example of a User struct which for the sake of simplicity we assume is defined inside this package:\n\n```go\npackage main\n\n// User is used as a base to provide tests for comments.\ntype User struct {\n\t// Unique sequential identifier.\n\tID int `json:\"id\" jsonschema:\"required\"`\n\t// Name of the user\n\tName string `json:\"name\"`\n}\n```\n\nTo get the comments provided into your JSON schema, use a regular `Reflector` and add the go code using an import module URL and path. Fully qualified go module paths cannot be determined reliably by the `go/parser` library, so we need to introduce this manually:\n\n```go\nr := new(Reflector)\nif err := r.AddGoComments(\"github.com/invopop/jsonschema\", \"./\"); err != nil {\n  // deal with error\n}\ns := r.Reflect(\u0026User{})\n// output\n```\n\nExpect the results to be similar to:\n\n```json\n{\n  \"$schema\": \"http://json-schema.org/draft/2020-12/schema\",\n  \"$ref\": \"#/$defs/User\",\n  \"$defs\": {\n    \"User\": {\n      \"required\": [\"id\"],\n      \"properties\": {\n        \"id\": {\n          \"type\": \"integer\",\n          \"description\": \"Unique sequential identifier.\"\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"description\": \"Name of the user\"\n        }\n      },\n      \"additionalProperties\": false,\n      \"type\": \"object\",\n      \"description\": \"User is used as a base to provide tests for comments.\"\n    }\n  }\n}\n```\n\n### Custom Key Naming\n\nIn some situations, the keys actually used to write files are different from Go structs'.\n\nThis is often the case when writing a configuration file to YAML or JSON from a Go struct, or when returning a JSON response for a Web API: APIs typically use snake_case, while Go uses PascalCase.\n\nYou can pass a `func(string) string` function to `Reflector`'s `KeyNamer` option to map Go field names to JSON key names and reflect the aforementioned transformations, without having to specify `json:\"...\"` on every struct field.\n\nFor example, consider the following struct\n\n```go\ntype User struct {\n  GivenName       string\n  PasswordSalted  []byte `json:\"salted_password\"`\n}\n```\n\nWe can transform field names to snake_case in the generated JSON schema:\n\n```go\nr := new(jsonschema.Reflector)\nr.KeyNamer = strcase.SnakeCase // from package github.com/stoewer/go-strcase\n\nr.Reflect(\u0026User{})\n```\n\nWill yield\n\n```diff\n  {\n    \"$schema\": \"http://json-schema.org/draft/2020-12/schema\",\n    \"$ref\": \"#/$defs/User\",\n    \"$defs\": {\n      \"User\": {\n        \"properties\": {\n-         \"GivenName\": {\n+         \"given_name\": {\n            \"type\": \"string\"\n          },\n          \"salted_password\": {\n            \"type\": \"string\",\n            \"contentEncoding\": \"base64\"\n          }\n        },\n        \"additionalProperties\": false,\n        \"type\": \"object\",\n-       \"required\": [\"GivenName\", \"salted_password\"]\n+       \"required\": [\"given_name\", \"salted_password\"]\n      }\n    }\n  }\n```\n\nAs you can see, if a field name has a `json:\"\"` tag set, the `key` argument to `KeyNamer` will have the value of that tag.\n\n### Custom Type Definitions\n\nSometimes it can be useful to have custom JSON Marshal and Unmarshal methods in your structs that automatically convert for example a string into an object.\n\nThis library will recognize and attempt to call four different methods that help you adjust schemas to your specific needs:\n\n- `JSONSchema() *Schema` - will prevent auto-generation of the schema so that you can provide your own definition.\n- `JSONSchemaExtend(schema *jsonschema.Schema)` - will be called _after_ the schema has been generated, allowing you to add or manipulate the fields easily.\n- `JSONSchemaAlias() any` - is called when reflecting the type of object and allows for an alternative to be used instead.\n- `JSONSchemaProperty(prop string) any` - will be called for every property inside a struct giving you the chance to provide an alternative object to convert into a schema.\n\nNote that all of these methods **must** be defined on a non-pointer object for them to be called.\n\nTake the following simplified example of a `CompactDate` that only includes the Year and Month:\n\n```go\ntype CompactDate struct {\n\tYear  int\n\tMonth int\n}\n\nfunc (d *CompactDate) UnmarshalJSON(data []byte) error {\n  if len(data) != 9 {\n    return errors.New(\"invalid compact date length\")\n  }\n  var err error\n  d.Year, err = strconv.Atoi(string(data[1:5]))\n  if err != nil {\n    return err\n  }\n  d.Month, err = strconv.Atoi(string(data[7:8]))\n  if err != nil {\n    return err\n  }\n  return nil\n}\n\nfunc (d *CompactDate) MarshalJSON() ([]byte, error) {\n  buf := new(bytes.Buffer)\n  buf.WriteByte('\"')\n  buf.WriteString(fmt.Sprintf(\"%d-%02d\", d.Year, d.Month))\n  buf.WriteByte('\"')\n  return buf.Bytes(), nil\n}\n\nfunc (CompactDate) JSONSchema() *Schema {\n\treturn \u0026Schema{\n\t\tType:        \"string\",\n\t\tTitle:       \"Compact Date\",\n\t\tDescription: \"Short date that only includes year and month\",\n\t\tPattern:     \"^[0-9]{4}-[0-1][0-9]$\",\n\t}\n}\n```\n\nThe resulting schema generated for this struct would look like:\n\n```json\n{\n  \"$schema\": \"http://json-schema.org/draft/2020-12/schema\",\n  \"$ref\": \"#/$defs/CompactDate\",\n  \"$defs\": {\n    \"CompactDate\": {\n      \"pattern\": \"^[0-9]{4}-[0-1][0-9]$\",\n      \"type\": \"string\",\n      \"title\": \"Compact Date\",\n      \"description\": \"Short date that only includes year and month\"\n    }\n  }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finvopop%2Fjsonschema","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finvopop%2Fjsonschema","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finvopop%2Fjsonschema/lists"}