{"id":13670045,"url":"https://github.com/xeipuuv/gojsonschema","last_synced_at":"2026-01-12T02:39:57.320Z","repository":{"id":7133899,"uuid":"8430202","full_name":"xeipuuv/gojsonschema","owner":"xeipuuv","description":"An implementation of JSON Schema, draft v4 v6 \u0026 v7 - Go language","archived":false,"fork":false,"pushed_at":"2024-06-28T22:32:47.000Z","size":586,"stargazers_count":2648,"open_issues_count":139,"forks_count":365,"subscribers_count":39,"default_branch":"master","last_synced_at":"2025-05-11T05:46:26.616Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","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/xeipuuv.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE-2.0.txt","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":"2013-02-26T10:23:25.000Z","updated_at":"2025-05-09T01:45:44.000Z","dependencies_parsed_at":"2023-01-13T14:17:10.343Z","dependency_job_id":"9d3359ee-7ecc-475e-892a-373b1693943d","html_url":"https://github.com/xeipuuv/gojsonschema","commit_stats":{"total_commits":423,"total_committers":61,"mean_commits":6.934426229508197,"dds":"0.40898345153664306","last_synced_commit":"b076d39a02e5015af0a2a96636e4cc479ecd9f45"},"previous_names":["sigu-399/gojsonschema"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xeipuuv%2Fgojsonschema","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xeipuuv%2Fgojsonschema/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xeipuuv%2Fgojsonschema/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xeipuuv%2Fgojsonschema/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xeipuuv","download_url":"https://codeload.github.com/xeipuuv/gojsonschema/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253523718,"owners_count":21921818,"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":[],"created_at":"2024-08-02T09:00:30.651Z","updated_at":"2026-01-12T02:39:57.314Z","avatar_url":"https://github.com/xeipuuv.png","language":"Go","funding_links":[],"categories":["Misc","Go","Golang"],"sub_categories":["Utils"],"readme":"[![GoDoc](https://godoc.org/github.com/xeipuuv/gojsonschema?status.svg)](https://godoc.org/github.com/xeipuuv/gojsonschema)\n[![Build Status](https://travis-ci.org/xeipuuv/gojsonschema.svg)](https://travis-ci.org/xeipuuv/gojsonschema)\n[![Go Report Card](https://goreportcard.com/badge/github.com/xeipuuv/gojsonschema)](https://goreportcard.com/report/github.com/xeipuuv/gojsonschema)\n\n# gojsonschema\n\n## Description\n\nAn implementation of JSON Schema for the Go  programming language. Supports draft-04, draft-06 and draft-07.\n\nReferences :\n\n* http://json-schema.org\n* http://json-schema.org/latest/json-schema-core.html\n* http://json-schema.org/latest/json-schema-validation.html\n\n## Installation\n\n```\ngo get github.com/xeipuuv/gojsonschema\n```\n\nDependencies :\n* [github.com/xeipuuv/gojsonpointer](https://github.com/xeipuuv/gojsonpointer)\n* [github.com/xeipuuv/gojsonreference](https://github.com/xeipuuv/gojsonreference)\n* [github.com/stretchr/testify/assert](https://github.com/stretchr/testify#assert-package)\n\n## Usage\n\n### Example\n\n```go\n\npackage main\n\nimport (\n    \"fmt\"\n    \"github.com/xeipuuv/gojsonschema\"\n)\n\nfunc main() {\n\n    schemaLoader := gojsonschema.NewReferenceLoader(\"file:///home/me/schema.json\")\n    documentLoader := gojsonschema.NewReferenceLoader(\"file:///home/me/document.json\")\n\n    result, err := gojsonschema.Validate(schemaLoader, documentLoader)\n    if err != nil {\n        panic(err.Error())\n    }\n\n    if result.Valid() {\n        fmt.Printf(\"The document is valid\\n\")\n    } else {\n        fmt.Printf(\"The document is not valid. see errors :\\n\")\n        for _, desc := range result.Errors() {\n            fmt.Printf(\"- %s\\n\", desc)\n        }\n    }\n}\n\n\n```\n\n#### Loaders\n\nThere are various ways to load your JSON data.\nIn order to load your schemas and documents,\nfirst declare an appropriate loader :\n\n* Web / HTTP, using a reference :\n\n```go\nloader := gojsonschema.NewReferenceLoader(\"http://www.some_host.com/schema.json\")\n```\n\n* Local file, using a reference :\n\n```go\nloader := gojsonschema.NewReferenceLoader(\"file:///home/me/schema.json\")\n```\n\nReferences use the URI scheme, the prefix (file://) and a full path to the file are required.\n\n* JSON strings :\n\n```go\nloader := gojsonschema.NewStringLoader(`{\"type\": \"string\"}`)\n```\n\n* Custom Go types :\n\n```go\nm := map[string]interface{}{\"type\": \"string\"}\nloader := gojsonschema.NewGoLoader(m)\n```\n\nAnd\n\n```go\ntype Root struct {\n\tUsers []User `json:\"users\"`\n}\n\ntype User struct {\n\tName string `json:\"name\"`\n}\n\n...\n\ndata := Root{}\ndata.Users = append(data.Users, User{\"John\"})\ndata.Users = append(data.Users, User{\"Sophia\"})\ndata.Users = append(data.Users, User{\"Bill\"})\n\nloader := gojsonschema.NewGoLoader(data)\n```\n\n#### Validation\n\nOnce the loaders are set, validation is easy :\n\n```go\nresult, err := gojsonschema.Validate(schemaLoader, documentLoader)\n```\n\nAlternatively, you might want to load a schema only once and process to multiple validations :\n\n```go\nschema, err := gojsonschema.NewSchema(schemaLoader)\n...\nresult1, err := schema.Validate(documentLoader1)\n...\nresult2, err := schema.Validate(documentLoader2)\n...\n// etc ...\n```\n\nTo check the result :\n\n```go\n    if result.Valid() {\n    \tfmt.Printf(\"The document is valid\\n\")\n    } else {\n        fmt.Printf(\"The document is not valid. see errors :\\n\")\n        for _, err := range result.Errors() {\n        \t// Err implements the ResultError interface\n            fmt.Printf(\"- %s\\n\", err)\n        }\n    }\n```\n\n\n## Loading local schemas\n\nBy default `file` and `http(s)` references to external schemas are loaded automatically via the file system or via http(s). An external schema can also be loaded using a `SchemaLoader`.\n\n```go\n\tsl := gojsonschema.NewSchemaLoader()\n\tloader1 := gojsonschema.NewStringLoader(`{ \"type\" : \"string\" }`)\n\terr := sl.AddSchema(\"http://some_host.com/string.json\", loader1)\n```\n\nAlternatively if your schema already has an `$id` you can use the `AddSchemas` function\n```go\n\tloader2 := gojsonschema.NewStringLoader(`{\n\t\t\t\"$id\" : \"http://some_host.com/maxlength.json\",\n\t\t\t\"maxLength\" : 5\n\t\t}`)\n\terr = sl.AddSchemas(loader2)\n```\n\nThe main schema should be passed to the `Compile` function. This main schema can then directly reference the added schemas without needing to download them.\n```go\n\tloader3 := gojsonschema.NewStringLoader(`{\n\t\t\"$id\" : \"http://some_host.com/main.json\",\n\t\t\"allOf\" : [\n\t\t\t{ \"$ref\" : \"http://some_host.com/string.json\" },\n\t\t\t{ \"$ref\" : \"http://some_host.com/maxlength.json\" }\n\t\t]\n\t}`)\n\n\tschema, err := sl.Compile(loader3)\n\n\tdocumentLoader := gojsonschema.NewStringLoader(`\"hello world\"`)\n\n\tresult, err := schema.Validate(documentLoader)\n```\n\nIt's also possible to pass a `ReferenceLoader` to the `Compile` function that references a loaded schema.\n\n```go\nerr = sl.AddSchemas(loader3)\nschema, err := sl.Compile(gojsonschema.NewReferenceLoader(\"http://some_host.com/main.json\"))\n``` \n\nSchemas added by `AddSchema` and `AddSchemas` are only validated when the entire schema is compiled, unless meta-schema validation is used.\n\n## Using a specific draft\nBy default `gojsonschema` will try to detect the draft of a schema by using the `$schema` keyword and parse it in a strict draft-04, draft-06 or draft-07 mode. If `$schema` is missing, or the draft version is not explicitely set, a hybrid mode is used which merges together functionality of all drafts into one mode.\n\nAutodectection can be turned off with the `AutoDetect` property. Specific draft versions can be specified with the `Draft` property.\n\n```go\nsl := gojsonschema.NewSchemaLoader()\nsl.Draft = gojsonschema.Draft7\nsl.AutoDetect = false\n```\n\nIf autodetection is on (default), a draft-07 schema can savely reference draft-04 schemas and vice-versa, as long as `$schema` is specified in all schemas.\n\n## Meta-schema validation\nSchemas that are added using the `AddSchema`, `AddSchemas` and `Compile` can be validated against their meta-schema by setting the `Validate` property.\n\nThe following example will produce an error as `multipleOf` must be a number. If `Validate` is off (default), this error is only returned at the `Compile` step. \n\n```go\nsl := gojsonschema.NewSchemaLoader()\nsl.Validate = true\nerr := sl.AddSchemas(gojsonschema.NewStringLoader(`{\n     \"$id\" : \"http://some_host.com/invalid.json\",\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"multipleOf\" : true\n}`))\n ```\n``` \n ```\n\nErrors returned by meta-schema validation are more readable and contain more information, which helps significantly if you are developing a schema.\n\nMeta-schema validation also works with a custom `$schema`. In case `$schema` is missing, or `AutoDetect` is set to `false`, the meta-schema of the used draft is used.\n\n\n## Working with Errors\n\nThe library handles string error codes which you can customize by creating your own gojsonschema.locale and setting it\n```go\ngojsonschema.Locale = YourCustomLocale{}\n```\n\nHowever, each error contains additional contextual information. \n\nNewer versions of `gojsonschema` may have new additional errors, so code that uses a custom locale will need to be updated when this happens.\n\n**err.Type()**: *string* Returns the \"type\" of error that occurred. Note you can also type check. See below\n\nNote: An error of RequiredType has an err.Type() return value of \"required\"\n\n    \"required\": RequiredError\n    \"invalid_type\": InvalidTypeError\n    \"number_any_of\": NumberAnyOfError\n    \"number_one_of\": NumberOneOfError\n    \"number_all_of\": NumberAllOfError\n    \"number_not\": NumberNotError\n    \"missing_dependency\": MissingDependencyError\n    \"internal\": InternalError\n    \"const\": ConstEror\n    \"enum\": EnumError\n    \"array_no_additional_items\": ArrayNoAdditionalItemsError\n    \"array_min_items\": ArrayMinItemsError\n    \"array_max_items\": ArrayMaxItemsError\n    \"unique\": ItemsMustBeUniqueError\n    \"contains\" : ArrayContainsError\n    \"array_min_properties\": ArrayMinPropertiesError\n    \"array_max_properties\": ArrayMaxPropertiesError\n    \"additional_property_not_allowed\": AdditionalPropertyNotAllowedError\n    \"invalid_property_pattern\": InvalidPropertyPatternError\n    \"invalid_property_name\":  InvalidPropertyNameError\n    \"string_gte\": StringLengthGTEError\n    \"string_lte\": StringLengthLTEError\n    \"pattern\": DoesNotMatchPatternError\n    \"multiple_of\": MultipleOfError\n    \"number_gte\": NumberGTEError\n    \"number_gt\": NumberGTError\n    \"number_lte\": NumberLTEError\n    \"number_lt\": NumberLTError\n    \"condition_then\" : ConditionThenError\n    \"condition_else\" : ConditionElseError\n\n**err.Value()**: *interface{}* Returns the value given\n\n**err.Context()**: *gojsonschema.JsonContext* Returns the context. This has a String() method that will print something like this: (root).firstName\n\n**err.Field()**: *string* Returns the fieldname in the format firstName, or for embedded properties, person.firstName. This returns the same as the String() method on *err.Context()* but removes the (root). prefix.\n\n**err.Description()**: *string* The error description. This is based on the locale you are using. See the beginning of this section for overwriting the locale with a custom implementation.\n\n**err.DescriptionFormat()**: *string* The error description format. This is relevant if you are adding custom validation errors afterwards to the result.\n\n**err.Details()**: *gojsonschema.ErrorDetails* Returns a map[string]interface{} of additional error details specific to the error. For example, GTE errors will have a \"min\" value, LTE will have a \"max\" value. See errors.go for a full description of all the error details. Every error always contains a \"field\" key that holds the value of *err.Field()*\n\nNote in most cases, the err.Details() will be used to generate replacement strings in your locales, and not used directly. These strings follow the text/template format i.e.\n```\n{{.field}} must be greater than or equal to {{.min}}\n```\n\nThe library allows you to specify custom template functions, should you require more complex error message handling.\n```go\ngojsonschema.ErrorTemplateFuncs = map[string]interface{}{\n\t\"allcaps\": func(s string) string {\n\t\treturn strings.ToUpper(s)\n\t},\n}\n```\n\nGiven the above definition, you can use the custom function `\"allcaps\"` in your localization templates:\n```\n{{allcaps .field}} must be greater than or equal to {{.min}}\n```\n\nThe above error message would then be rendered with the `field` value in capital letters. For example:\n```\n\"PASSWORD must be greater than or equal to 8\"\n```\n\nLearn more about what types of template functions you can use in `ErrorTemplateFuncs` by referring to Go's [text/template FuncMap](https://golang.org/pkg/text/template/#FuncMap) type.\n\n## Formats\nJSON Schema allows for optional \"format\" property to validate instances against well-known formats. gojsonschema ships with all of the formats defined in the spec that you can use like this:\n\n````json\n{\"type\": \"string\", \"format\": \"email\"}\n````\n\nNot all formats defined in draft-07 are available. Implemented formats are:\n\n* `date`\n* `time`\n* `date-time`\n* `hostname`. Subdomains that start with a number are also supported, but this means that it doesn't strictly follow [RFC1034](http://tools.ietf.org/html/rfc1034#section-3.5) and has the implication that ipv4 addresses are also recognized as valid hostnames.\n* `email`. Go's email parser deviates slightly from [RFC5322](https://tools.ietf.org/html/rfc5322). Includes unicode support.\n* `idn-email`. Same caveat as `email`.\n* `ipv4`\n* `ipv6`\n* `uri`. Includes unicode support.\n* `uri-reference`. Includes unicode support.\n* `iri`\n* `iri-reference`\n* `uri-template`\n* `uuid`\n* `regex`. Go uses the [RE2](https://github.com/google/re2/wiki/Syntax) engine and is not [ECMA262](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf) compatible.\n* `json-pointer`\n* `relative-json-pointer`\n\n`email`, `uri` and `uri-reference` use the same validation code as their unicode counterparts `idn-email`, `iri` and `iri-reference`. If you rely on unicode support you should use the specific \nunicode enabled formats for the sake of interoperability as other implementations might not support unicode in the regular formats.\n\nThe validation code for `uri`, `idn-email` and their relatives use mostly standard library code.\n\nFor repetitive or more complex formats, you can create custom format checkers and add them to gojsonschema like this:\n\n```go\n// Define the format checker\ntype RoleFormatChecker struct {}\n\n// Ensure it meets the gojsonschema.FormatChecker interface\nfunc (f RoleFormatChecker) IsFormat(input interface{}) bool {\n\n    asString, ok := input.(string)\n    if ok == false {\n        return false\n    }\n\n    return strings.HasPrefix(\"ROLE_\", asString)\n}\n\n// Add it to the library\ngojsonschema.FormatCheckers.Add(\"role\", RoleFormatChecker{})\n````\n\nNow to use in your json schema:\n````json\n{\"type\": \"string\", \"format\": \"role\"}\n````\n\nAnother example would be to check if the provided integer matches an id on database:\n\nJSON schema:\n```json\n{\"type\": \"integer\", \"format\": \"ValidUserId\"}\n```\n\n```go\n// Define the format checker\ntype ValidUserIdFormatChecker struct {}\n\n// Ensure it meets the gojsonschema.FormatChecker interface\nfunc (f ValidUserIdFormatChecker) IsFormat(input interface{}) bool {\n\n    asFloat64, ok := input.(float64) // Numbers are always float64 here\n    if ok == false {\n        return false\n    }\n\n    // XXX\n    // do the magic on the database looking for the int(asFloat64)\n\n    return true\n}\n\n// Add it to the library\ngojsonschema.FormatCheckers.Add(\"ValidUserId\", ValidUserIdFormatChecker{})\n````\n\nFormats can also be removed, for example if you want to override one of the formats that is defined by default.\n\n```go\ngojsonschema.FormatCheckers.Remove(\"hostname\")\n```\n\n\n## Additional custom validation\nAfter the validation has run and you have the results, you may add additional\nerrors using `Result.AddError`. This is useful to maintain the same format within the resultset instead\nof having to add special exceptions for your own errors. Below is an example.\n\n```go\ntype AnswerInvalidError struct {\n    gojsonschema.ResultErrorFields\n}\n\nfunc newAnswerInvalidError(context *gojsonschema.JsonContext, value interface{}, details gojsonschema.ErrorDetails) *AnswerInvalidError {\n    err := AnswerInvalidError{}\n    err.SetContext(context)\n    err.SetType(\"custom_invalid_error\")\n    // it is important to use SetDescriptionFormat() as this is used to call SetDescription() after it has been parsed\n    // using the description of err will be overridden by this.\n    err.SetDescriptionFormat(\"Answer to the Ultimate Question of Life, the Universe, and Everything is {{.answer}}\")\n    err.SetValue(value)\n    err.SetDetails(details)\n\n    return \u0026err\n}\n\nfunc main() {\n    // ...\n    schema, err := gojsonschema.NewSchema(schemaLoader)\n    result, err := gojsonschema.Validate(schemaLoader, documentLoader)\n\n    if true { // some validation\n        jsonContext := gojsonschema.NewJsonContext(\"question\", nil)\n        errDetail := gojsonschema.ErrorDetails{\n            \"answer\": 42,\n        }\n        result.AddError(\n            newAnswerInvalidError(\n                gojsonschema.NewJsonContext(\"answer\", jsonContext),\n                52,\n                errDetail,\n            ),\n            errDetail,\n        )\n    }\n\n    return result, err\n\n}\n```\n\nThis is especially useful if you want to add validation beyond what the\njson schema drafts can provide such business specific logic.\n\n## Uses\n\ngojsonschema uses the following test suite :\n\nhttps://github.com/json-schema/JSON-Schema-Test-Suite\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxeipuuv%2Fgojsonschema","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxeipuuv%2Fgojsonschema","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxeipuuv%2Fgojsonschema/lists"}