diff options
| author | Taras Madan <tarasmadan@google.com> | 2025-01-22 16:07:17 +0100 |
|---|---|---|
| committer | Taras Madan <tarasmadan@google.com> | 2025-01-23 10:42:36 +0000 |
| commit | 7b4377ad9d8a7205416df8d6217ef2b010f89481 (patch) | |
| tree | e6fec4fd12ff807a16d847923f501075bf71d16c /vendor/github.com/santhosh-tekuri | |
| parent | 475a4c203afb8b7d3af51c4fd32bb170ff32a45e (diff) | |
vendor: delete
Diffstat (limited to 'vendor/github.com/santhosh-tekuri')
16 files changed, 0 insertions, 4913 deletions
diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v5/.gitignore b/vendor/github.com/santhosh-tekuri/jsonschema/v5/.gitignore deleted file mode 100644 index 3c0af3825..000000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/v5/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.vscode -.idea -*.swp -cmd/jv/jv diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v5/.gitmodules b/vendor/github.com/santhosh-tekuri/jsonschema/v5/.gitmodules deleted file mode 100644 index 314da31c5..000000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/v5/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "testdata/JSON-Schema-Test-Suite"] - path = testdata/JSON-Schema-Test-Suite - url = https://github.com/json-schema-org/JSON-Schema-Test-Suite.git diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v5/LICENSE b/vendor/github.com/santhosh-tekuri/jsonschema/v5/LICENSE deleted file mode 100644 index 19dc35b24..000000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/v5/LICENSE +++ /dev/null @@ -1,175 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability.
\ No newline at end of file diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v5/README.md b/vendor/github.com/santhosh-tekuri/jsonschema/v5/README.md deleted file mode 100644 index b0d05054c..000000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/v5/README.md +++ /dev/null @@ -1,220 +0,0 @@ -# jsonschema v5.3.1 - -[](https://opensource.org/licenses/Apache-2.0) -[](https://pkg.go.dev/github.com/santhosh-tekuri/jsonschema/v5) -[](https://goreportcard.com/report/github.com/santhosh-tekuri/jsonschema/v5) -[](https://github.com/santhosh-tekuri/jsonschema/actions/workflows/go.yaml) -[](https://codecov.io/gh/santhosh-tekuri/jsonschema) - -Package jsonschema provides json-schema compilation and validation. - -[Benchmarks](https://dev.to/vearutop/benchmarking-correctness-and-performance-of-go-json-schema-validators-3247) - -### Features: - - implements - [draft 2020-12](https://json-schema.org/specification-links.html#2020-12), - [draft 2019-09](https://json-schema.org/specification-links.html#draft-2019-09-formerly-known-as-draft-8), - [draft-7](https://json-schema.org/specification-links.html#draft-7), - [draft-6](https://json-schema.org/specification-links.html#draft-6), - [draft-4](https://json-schema.org/specification-links.html#draft-4) - - fully compliant with [JSON-Schema-Test-Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite), (excluding some optional) - - list of optional tests that are excluded can be found in schema_test.go(variable [skipTests](https://github.com/santhosh-tekuri/jsonschema/blob/master/schema_test.go#L24)) - - validates schemas against meta-schema - - full support of remote references - - support of recursive references between schemas - - detects infinite loop in schemas - - thread safe validation - - rich, intuitive hierarchial error messages with json-pointers to exact location - - supports output formats flag, basic and detailed - - supports enabling format and content Assertions in draft2019-09 or above - - change `Compiler.AssertFormat`, `Compiler.AssertContent` to `true` - - compiled schema can be introspected. easier to develop tools like generating go structs given schema - - supports user-defined keywords via [extensions](https://pkg.go.dev/github.com/santhosh-tekuri/jsonschema/v5/#example-package-Extension) - - implements following formats (supports [user-defined](https://pkg.go.dev/github.com/santhosh-tekuri/jsonschema/v5/#example-package-UserDefinedFormat)) - - date-time, date, time, duration, period (supports leap-second) - - uuid, hostname, email - - ip-address, ipv4, ipv6 - - uri, uriref, uri-template(limited validation) - - json-pointer, relative-json-pointer - - regex, format - - implements following contentEncoding (supports [user-defined](https://pkg.go.dev/github.com/santhosh-tekuri/jsonschema/v5/#example-package-UserDefinedContent)) - - base64 - - implements following contentMediaType (supports [user-defined](https://pkg.go.dev/github.com/santhosh-tekuri/jsonschema/v5/#example-package-UserDefinedContent)) - - application/json - - can load from files/http/https/[string](https://pkg.go.dev/github.com/santhosh-tekuri/jsonschema/v5/#example-package-FromString)/[]byte/io.Reader (supports [user-defined](https://pkg.go.dev/github.com/santhosh-tekuri/jsonschema/v5/#example-package-UserDefinedLoader)) - - -see examples in [godoc](https://pkg.go.dev/github.com/santhosh-tekuri/jsonschema/v5) - -The schema is compiled against the version specified in `$schema` property. -If "$schema" property is missing, it uses latest draft which currently implemented -by this library. - -You can force to use specific version, when `$schema` is missing, as follows: - -```go -compiler := jsonschema.NewCompiler() -compiler.Draft = jsonschema.Draft4 -``` - -This package supports loading json-schema from filePath and fileURL. - -To load json-schema from HTTPURL, add following import: - -```go -import _ "github.com/santhosh-tekuri/jsonschema/v5/httploader" -``` - -## Rich Errors - -The ValidationError returned by Validate method contains detailed context to understand why and where the error is. - -schema.json: -```json -{ - "$ref": "t.json#/definitions/employee" -} -``` - -t.json: -```json -{ - "definitions": { - "employee": { - "type": "string" - } - } -} -``` - -doc.json: -```json -1 -``` - -assuming `err` is the ValidationError returned when `doc.json` validated with `schema.json`, -```go -fmt.Printf("%#v\n", err) // using %#v prints errors hierarchy -``` -Prints: -``` -[I#] [S#] doesn't validate with file:///Users/santhosh/jsonschema/schema.json# - [I#] [S#/$ref] doesn't validate with 'file:///Users/santhosh/jsonschema/t.json#/definitions/employee' - [I#] [S#/definitions/employee/type] expected string, but got number -``` - -Here `I` stands for instance document and `S` stands for schema document. -The json-fragments that caused error in instance and schema documents are represented using json-pointer notation. -Nested causes are printed with indent. - -To output `err` in `flag` output format: -```go -b, _ := json.MarshalIndent(err.FlagOutput(), "", " ") -fmt.Println(string(b)) -``` -Prints: -```json -{ - "valid": false -} -``` -To output `err` in `basic` output format: -```go -b, _ := json.MarshalIndent(err.BasicOutput(), "", " ") -fmt.Println(string(b)) -``` -Prints: -```json -{ - "valid": false, - "errors": [ - { - "keywordLocation": "", - "absoluteKeywordLocation": "file:///Users/santhosh/jsonschema/schema.json#", - "instanceLocation": "", - "error": "doesn't validate with file:///Users/santhosh/jsonschema/schema.json#" - }, - { - "keywordLocation": "/$ref", - "absoluteKeywordLocation": "file:///Users/santhosh/jsonschema/schema.json#/$ref", - "instanceLocation": "", - "error": "doesn't validate with 'file:///Users/santhosh/jsonschema/t.json#/definitions/employee'" - }, - { - "keywordLocation": "/$ref/type", - "absoluteKeywordLocation": "file:///Users/santhosh/jsonschema/t.json#/definitions/employee/type", - "instanceLocation": "", - "error": "expected string, but got number" - } - ] -} -``` -To output `err` in `detailed` output format: -```go -b, _ := json.MarshalIndent(err.DetailedOutput(), "", " ") -fmt.Println(string(b)) -``` -Prints: -```json -{ - "valid": false, - "keywordLocation": "", - "absoluteKeywordLocation": "file:///Users/santhosh/jsonschema/schema.json#", - "instanceLocation": "", - "errors": [ - { - "valid": false, - "keywordLocation": "/$ref", - "absoluteKeywordLocation": "file:///Users/santhosh/jsonschema/schema.json#/$ref", - "instanceLocation": "", - "errors": [ - { - "valid": false, - "keywordLocation": "/$ref/type", - "absoluteKeywordLocation": "file:///Users/santhosh/jsonschema/t.json#/definitions/employee/type", - "instanceLocation": "", - "error": "expected string, but got number" - } - ] - } - ] -} -``` - -## CLI - -to install `go install github.com/santhosh-tekuri/jsonschema/cmd/jv@latest` - -```bash -jv [-draft INT] [-output FORMAT] [-assertformat] [-assertcontent] <json-schema> [<json-or-yaml-doc>]... - -assertcontent - enable content assertions with draft >= 2019 - -assertformat - enable format assertions with draft >= 2019 - -draft int - draft used when '$schema' attribute is missing. valid values 4, 5, 7, 2019, 2020 (default 2020) - -output string - output format. valid values flag, basic, detailed -``` - -if no `<json-or-yaml-doc>` arguments are passed, it simply validates the `<json-schema>`. -if `$schema` attribute is missing in schema, it uses latest version. this can be overridden by passing `-draft` flag - -exit-code is 1, if there are any validation errors - -`jv` can also validate yaml files. It also accepts schema from yaml files. - -## Validating YAML Documents - -since yaml supports non-string keys, such yaml documents are rendered as invalid json documents. - -most yaml parser use `map[interface{}]interface{}` for object, -whereas json parser uses `map[string]interface{}`. - -so we need to manually convert them to `map[string]interface{}`. -below code shows such conversion by `toStringKeys` function. - -https://play.golang.org/p/Hhax3MrtD8r - -NOTE: if you are using `gopkg.in/yaml.v3`, then you do not need such conversion. since this library -returns `map[string]interface{}` if all keys are strings.
\ No newline at end of file diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v5/compiler.go b/vendor/github.com/santhosh-tekuri/jsonschema/v5/compiler.go deleted file mode 100644 index fdb68e648..000000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/v5/compiler.go +++ /dev/null @@ -1,812 +0,0 @@ -package jsonschema - -import ( - "encoding/json" - "fmt" - "io" - "math/big" - "regexp" - "strconv" - "strings" -) - -// A Compiler represents a json-schema compiler. -type Compiler struct { - // Draft represents the draft used when '$schema' attribute is missing. - // - // This defaults to latest supported draft (currently 2020-12). - Draft *Draft - resources map[string]*resource - - // Extensions is used to register extensions. - extensions map[string]extension - - // ExtractAnnotations tells whether schema annotations has to be extracted - // in compiled Schema or not. - ExtractAnnotations bool - - // LoadURL loads the document at given absolute URL. - // - // If nil, package global LoadURL is used. - LoadURL func(s string) (io.ReadCloser, error) - - // Formats can be registered by adding to this map. Key is format name, - // value is function that knows how to validate that format. - Formats map[string]func(interface{}) bool - - // AssertFormat for specifications >= draft2019-09. - AssertFormat bool - - // Decoders can be registered by adding to this map. Key is encoding name, - // value is function that knows how to decode string in that format. - Decoders map[string]func(string) ([]byte, error) - - // MediaTypes can be registered by adding to this map. Key is mediaType name, - // value is function that knows how to validate that mediaType. - MediaTypes map[string]func([]byte) error - - // AssertContent for specifications >= draft2019-09. - AssertContent bool -} - -// Compile parses json-schema at given url returns, if successful, -// a Schema object that can be used to match against json. -// -// Returned error can be *SchemaError -func Compile(url string) (*Schema, error) { - return NewCompiler().Compile(url) -} - -// MustCompile is like Compile but panics if the url cannot be compiled to *Schema. -// It simplifies safe initialization of global variables holding compiled Schemas. -func MustCompile(url string) *Schema { - return NewCompiler().MustCompile(url) -} - -// CompileString parses and compiles the given schema with given base url. -func CompileString(url, schema string) (*Schema, error) { - c := NewCompiler() - if err := c.AddResource(url, strings.NewReader(schema)); err != nil { - return nil, err - } - return c.Compile(url) -} - -// MustCompileString is like CompileString but panics on error. -// It simplified safe initialization of global variables holding compiled Schema. -func MustCompileString(url, schema string) *Schema { - c := NewCompiler() - if err := c.AddResource(url, strings.NewReader(schema)); err != nil { - panic(err) - } - return c.MustCompile(url) -} - -// NewCompiler returns a json-schema Compiler object. -// if '$schema' attribute is missing, it is treated as draft7. to change this -// behavior change Compiler.Draft value -func NewCompiler() *Compiler { - return &Compiler{ - Draft: latest, - resources: make(map[string]*resource), - Formats: make(map[string]func(interface{}) bool), - Decoders: make(map[string]func(string) ([]byte, error)), - MediaTypes: make(map[string]func([]byte) error), - extensions: make(map[string]extension), - } -} - -// AddResource adds in-memory resource to the compiler. -// -// Note that url must not have fragment -func (c *Compiler) AddResource(url string, r io.Reader) error { - res, err := newResource(url, r) - if err != nil { - return err - } - c.resources[res.url] = res - return nil -} - -// MustCompile is like Compile but panics if the url cannot be compiled to *Schema. -// It simplifies safe initialization of global variables holding compiled Schemas. -func (c *Compiler) MustCompile(url string) *Schema { - s, err := c.Compile(url) - if err != nil { - panic(fmt.Sprintf("jsonschema: %#v", err)) - } - return s -} - -// Compile parses json-schema at given url returns, if successful, -// a Schema object that can be used to match against json. -// -// error returned will be of type *SchemaError -func (c *Compiler) Compile(url string) (*Schema, error) { - // make url absolute - u, err := toAbs(url) - if err != nil { - return nil, &SchemaError{url, err} - } - url = u - - sch, err := c.compileURL(url, nil, "#") - if err != nil { - err = &SchemaError{url, err} - } - return sch, err -} - -func (c *Compiler) findResource(url string) (*resource, error) { - if _, ok := c.resources[url]; !ok { - // load resource - var rdr io.Reader - if sch, ok := vocabSchemas[url]; ok { - rdr = strings.NewReader(sch) - } else { - loadURL := LoadURL - if c.LoadURL != nil { - loadURL = c.LoadURL - } - r, err := loadURL(url) - if err != nil { - return nil, err - } - defer r.Close() - rdr = r - } - if err := c.AddResource(url, rdr); err != nil { - return nil, err - } - } - - r := c.resources[url] - if r.draft != nil { - return r, nil - } - - // set draft - r.draft = c.Draft - if m, ok := r.doc.(map[string]interface{}); ok { - if sch, ok := m["$schema"]; ok { - sch, ok := sch.(string) - if !ok { - return nil, fmt.Errorf("jsonschema: invalid $schema in %s", url) - } - if !isURI(sch) { - return nil, fmt.Errorf("jsonschema: $schema must be uri in %s", url) - } - r.draft = findDraft(sch) - if r.draft == nil { - sch, _ := split(sch) - if sch == url { - return nil, fmt.Errorf("jsonschema: unsupported draft in %s", url) - } - mr, err := c.findResource(sch) - if err != nil { - return nil, err - } - r.draft = mr.draft - } - } - } - - id, err := r.draft.resolveID(r.url, r.doc) - if err != nil { - return nil, err - } - if id != "" { - r.url = id - } - - if err := r.fillSubschemas(c, r); err != nil { - return nil, err - } - - return r, nil -} - -func (c *Compiler) compileURL(url string, stack []schemaRef, ptr string) (*Schema, error) { - // if url points to a draft, return Draft.meta - if d := findDraft(url); d != nil && d.meta != nil { - return d.meta, nil - } - - b, f := split(url) - r, err := c.findResource(b) - if err != nil { - return nil, err - } - return c.compileRef(r, stack, ptr, r, f) -} - -func (c *Compiler) compileRef(r *resource, stack []schemaRef, refPtr string, res *resource, ref string) (*Schema, error) { - base := r.baseURL(res.floc) - ref, err := resolveURL(base, ref) - if err != nil { - return nil, err - } - - u, f := split(ref) - sr := r.findResource(u) - if sr == nil { - // external resource - return c.compileURL(ref, stack, refPtr) - } - - // ensure root resource is always compiled first. - // this is required to get schema.meta from root resource - if r.schema == nil { - r.schema = newSchema(r.url, r.floc, r.draft, r.doc) - if _, err := c.compile(r, nil, schemaRef{"#", r.schema, false}, r); err != nil { - return nil, err - } - } - - sr, err = r.resolveFragment(c, sr, f) - if err != nil { - return nil, err - } - if sr == nil { - return nil, fmt.Errorf("jsonschema: %s not found", ref) - } - - if sr.schema != nil { - if err := checkLoop(stack, schemaRef{refPtr, sr.schema, false}); err != nil { - return nil, err - } - return sr.schema, nil - } - - sr.schema = newSchema(r.url, sr.floc, r.draft, sr.doc) - return c.compile(r, stack, schemaRef{refPtr, sr.schema, false}, sr) -} - -func (c *Compiler) compileDynamicAnchors(r *resource, res *resource) error { - if r.draft.version < 2020 { - return nil - } - - rr := r.listResources(res) - rr = append(rr, res) - for _, sr := range rr { - if m, ok := sr.doc.(map[string]interface{}); ok { - if _, ok := m["$dynamicAnchor"]; ok { - sch, err := c.compileRef(r, nil, "IGNORED", r, sr.floc) - if err != nil { - return err - } - res.schema.dynamicAnchors = append(res.schema.dynamicAnchors, sch) - } - } - } - return nil -} - -func (c *Compiler) compile(r *resource, stack []schemaRef, sref schemaRef, res *resource) (*Schema, error) { - if err := c.compileDynamicAnchors(r, res); err != nil { - return nil, err - } - - switch v := res.doc.(type) { - case bool: - res.schema.Always = &v - return res.schema, nil - default: - return res.schema, c.compileMap(r, stack, sref, res) - } -} - -func (c *Compiler) compileMap(r *resource, stack []schemaRef, sref schemaRef, res *resource) error { - m := res.doc.(map[string]interface{}) - - if err := checkLoop(stack, sref); err != nil { - return err - } - stack = append(stack, sref) - - var s = res.schema - var err error - - if r == res { // root schema - if sch, ok := m["$schema"]; ok { - sch := sch.(string) - if d := findDraft(sch); d != nil { - s.meta = d.meta - } else { - if s.meta, err = c.compileRef(r, stack, "$schema", res, sch); err != nil { - return err - } - } - } - } - - if ref, ok := m["$ref"]; ok { - s.Ref, err = c.compileRef(r, stack, "$ref", res, ref.(string)) - if err != nil { - return err - } - if r.draft.version < 2019 { - // All other properties in a "$ref" object MUST be ignored - return nil - } - } - - if r.draft.version >= 2019 { - if r == res { // root schema - if vocab, ok := m["$vocabulary"]; ok { - for url, reqd := range vocab.(map[string]interface{}) { - if reqd, ok := reqd.(bool); ok && !reqd { - continue - } - if !r.draft.isVocab(url) { - return fmt.Errorf("jsonschema: unsupported vocab %q in %s", url, res) - } - s.vocab = append(s.vocab, url) - } - } else { - s.vocab = r.draft.defaultVocab - } - } - - if ref, ok := m["$recursiveRef"]; ok { - s.RecursiveRef, err = c.compileRef(r, stack, "$recursiveRef", res, ref.(string)) - if err != nil { - return err - } - } - } - if r.draft.version >= 2020 { - if dref, ok := m["$dynamicRef"]; ok { - s.DynamicRef, err = c.compileRef(r, stack, "$dynamicRef", res, dref.(string)) - if err != nil { - return err - } - if dref, ok := dref.(string); ok { - _, frag := split(dref) - if frag != "#" && !strings.HasPrefix(frag, "#/") { - // frag is anchor - s.dynamicRefAnchor = frag[1:] - } - } - } - } - - loadInt := func(pname string) int { - if num, ok := m[pname]; ok { - i, _ := num.(json.Number).Float64() - return int(i) - } - return -1 - } - - loadRat := func(pname string) *big.Rat { - if num, ok := m[pname]; ok { - r, _ := new(big.Rat).SetString(string(num.(json.Number))) - return r - } - return nil - } - - if r.draft.version < 2019 || r.schema.meta.hasVocab("validation") { - if t, ok := m["type"]; ok { - switch t := t.(type) { - case string: - s.Types = []string{t} - case []interface{}: - s.Types = toStrings(t) - } - } - - if e, ok := m["enum"]; ok { - s.Enum = e.([]interface{}) - allPrimitives := true - for _, item := range s.Enum { - switch jsonType(item) { - case "object", "array": - allPrimitives = false - break - } - } - s.enumError = "enum failed" - if allPrimitives { - if len(s.Enum) == 1 { - s.enumError = fmt.Sprintf("value must be %#v", s.Enum[0]) - } else { - strEnum := make([]string, len(s.Enum)) - for i, item := range s.Enum { - strEnum[i] = fmt.Sprintf("%#v", item) - } - s.enumError = fmt.Sprintf("value must be one of %s", strings.Join(strEnum, ", ")) - } - } - } - - s.Minimum = loadRat("minimum") - if exclusive, ok := m["exclusiveMinimum"]; ok { - if exclusive, ok := exclusive.(bool); ok { - if exclusive { - s.Minimum, s.ExclusiveMinimum = nil, s.Minimum - } - } else { - s.ExclusiveMinimum = loadRat("exclusiveMinimum") - } - } - - s.Maximum = loadRat("maximum") - if exclusive, ok := m["exclusiveMaximum"]; ok { - if exclusive, ok := exclusive.(bool); ok { - if exclusive { - s.Maximum, s.ExclusiveMaximum = nil, s.Maximum - } - } else { - s.ExclusiveMaximum = loadRat("exclusiveMaximum") - } - } - - s.MultipleOf = loadRat("multipleOf") - - s.MinProperties, s.MaxProperties = loadInt("minProperties"), loadInt("maxProperties") - - if req, ok := m["required"]; ok { - s.Required = toStrings(req.([]interface{})) - } - - s.MinItems, s.MaxItems = loadInt("minItems"), loadInt("maxItems") - - if unique, ok := m["uniqueItems"]; ok { - s.UniqueItems = unique.(bool) - } - - s.MinLength, s.MaxLength = loadInt("minLength"), loadInt("maxLength") - - if pattern, ok := m["pattern"]; ok { - s.Pattern = regexp.MustCompile(pattern.(string)) - } - - if r.draft.version >= 2019 { - s.MinContains, s.MaxContains = loadInt("minContains"), loadInt("maxContains") - if s.MinContains == -1 { - s.MinContains = 1 - } - - if deps, ok := m["dependentRequired"]; ok { - deps := deps.(map[string]interface{}) - s.DependentRequired = make(map[string][]string, len(deps)) - for pname, pvalue := range deps { - s.DependentRequired[pname] = toStrings(pvalue.([]interface{})) - } - } - } - } - - compile := func(stack []schemaRef, ptr string) (*Schema, error) { - return c.compileRef(r, stack, ptr, res, r.url+res.floc+"/"+ptr) - } - - loadSchema := func(pname string, stack []schemaRef) (*Schema, error) { - if _, ok := m[pname]; ok { - return compile(stack, escape(pname)) - } - return nil, nil - } - - loadSchemas := func(pname string, stack []schemaRef) ([]*Schema, error) { - if pvalue, ok := m[pname]; ok { - pvalue := pvalue.([]interface{}) - schemas := make([]*Schema, len(pvalue)) - for i := range pvalue { - sch, err := compile(stack, escape(pname)+"/"+strconv.Itoa(i)) - if err != nil { - return nil, err - } - schemas[i] = sch - } - return schemas, nil - } - return nil, nil - } - - if r.draft.version < 2019 || r.schema.meta.hasVocab("applicator") { - if s.Not, err = loadSchema("not", stack); err != nil { - return err - } - if s.AllOf, err = loadSchemas("allOf", stack); err != nil { - return err - } - if s.AnyOf, err = loadSchemas("anyOf", stack); err != nil { - return err - } - if s.OneOf, err = loadSchemas("oneOf", stack); err != nil { - return err - } - - if props, ok := m["properties"]; ok { - props := props.(map[string]interface{}) - s.Properties = make(map[string]*Schema, len(props)) - for pname := range props { - s.Properties[pname], err = compile(nil, "properties/"+escape(pname)) - if err != nil { - return err - } - } - } - - if regexProps, ok := m["regexProperties"]; ok { - s.RegexProperties = regexProps.(bool) - } - - if patternProps, ok := m["patternProperties"]; ok { - patternProps := patternProps.(map[string]interface{}) - s.PatternProperties = make(map[*regexp.Regexp]*Schema, len(patternProps)) - for pattern := range patternProps { - s.PatternProperties[regexp.MustCompile(pattern)], err = compile(nil, "patternProperties/"+escape(pattern)) - if err != nil { - return err - } - } - } - - if additionalProps, ok := m["additionalProperties"]; ok { - switch additionalProps := additionalProps.(type) { - case bool: - s.AdditionalProperties = additionalProps - case map[string]interface{}: - s.AdditionalProperties, err = compile(nil, "additionalProperties") - if err != nil { - return err - } - } - } - - if deps, ok := m["dependencies"]; ok { - deps := deps.(map[string]interface{}) - s.Dependencies = make(map[string]interface{}, len(deps)) - for pname, pvalue := range deps { - switch pvalue := pvalue.(type) { - case []interface{}: - s.Dependencies[pname] = toStrings(pvalue) - default: - s.Dependencies[pname], err = compile(stack, "dependencies/"+escape(pname)) - if err != nil { - return err - } - } - } - } - - if r.draft.version >= 6 { - if s.PropertyNames, err = loadSchema("propertyNames", nil); err != nil { - return err - } - if s.Contains, err = loadSchema("contains", nil); err != nil { - return err - } - } - - if r.draft.version >= 7 { - if m["if"] != nil { - if s.If, err = loadSchema("if", stack); err != nil { - return err - } - if s.Then, err = loadSchema("then", stack); err != nil { - return err - } - if s.Else, err = loadSchema("else", stack); err != nil { - return err - } - } - } - if r.draft.version >= 2019 { - if deps, ok := m["dependentSchemas"]; ok { - deps := deps.(map[string]interface{}) - s.DependentSchemas = make(map[string]*Schema, len(deps)) - for pname := range deps { - s.DependentSchemas[pname], err = compile(stack, "dependentSchemas/"+escape(pname)) - if err != nil { - return err - } - } - } - } - - if r.draft.version >= 2020 { - if s.PrefixItems, err = loadSchemas("prefixItems", nil); err != nil { - return err - } - if s.Items2020, err = loadSchema("items", nil); err != nil { - return err - } - } else { - if items, ok := m["items"]; ok { - switch items.(type) { - case []interface{}: - s.Items, err = loadSchemas("items", nil) - if err != nil { - return err - } - if additionalItems, ok := m["additionalItems"]; ok { - switch additionalItems := additionalItems.(type) { - case bool: - s.AdditionalItems = additionalItems - case map[string]interface{}: - s.AdditionalItems, err = compile(nil, "additionalItems") - if err != nil { - return err - } - } - } - default: - s.Items, err = compile(nil, "items") - if err != nil { - return err - } - } - } - } - - } - - // unevaluatedXXX keywords were in "applicator" vocab in 2019, but moved to new vocab "unevaluated" in 2020 - if (r.draft.version == 2019 && r.schema.meta.hasVocab("applicator")) || (r.draft.version >= 2020 && r.schema.meta.hasVocab("unevaluated")) { - if s.UnevaluatedProperties, err = loadSchema("unevaluatedProperties", nil); err != nil { - return err - } - if s.UnevaluatedItems, err = loadSchema("unevaluatedItems", nil); err != nil { - return err - } - if r.draft.version >= 2020 { - // any item in an array that passes validation of the contains schema is considered "evaluated" - s.ContainsEval = true - } - } - - if format, ok := m["format"]; ok { - s.Format = format.(string) - if r.draft.version < 2019 || c.AssertFormat || r.schema.meta.hasVocab("format-assertion") { - if format, ok := c.Formats[s.Format]; ok { - s.format = format - } else { - s.format, _ = Formats[s.Format] - } - } - } - - if c.ExtractAnnotations { - if title, ok := m["title"]; ok { - s.Title = title.(string) - } - if description, ok := m["description"]; ok { - s.Description = description.(string) - } - s.Default = m["default"] - } - - if r.draft.version >= 6 { - if c, ok := m["const"]; ok { - s.Constant = []interface{}{c} - } - } - - if r.draft.version >= 7 { - if encoding, ok := m["contentEncoding"]; ok { - s.ContentEncoding = encoding.(string) - if decoder, ok := c.Decoders[s.ContentEncoding]; ok { - s.decoder = decoder - } else { - s.decoder, _ = Decoders[s.ContentEncoding] - } - } - if mediaType, ok := m["contentMediaType"]; ok { - s.ContentMediaType = mediaType.(string) - if mediaType, ok := c.MediaTypes[s.ContentMediaType]; ok { - s.mediaType = mediaType - } else { - s.mediaType, _ = MediaTypes[s.ContentMediaType] - } - if s.ContentSchema, err = loadSchema("contentSchema", stack); err != nil { - return err - } - } - if c.ExtractAnnotations { - if comment, ok := m["$comment"]; ok { - s.Comment = comment.(string) - } - if readOnly, ok := m["readOnly"]; ok { - s.ReadOnly = readOnly.(bool) - } - if writeOnly, ok := m["writeOnly"]; ok { - s.WriteOnly = writeOnly.(bool) - } - if examples, ok := m["examples"]; ok { - s.Examples = examples.([]interface{}) - } - } - } - - if r.draft.version >= 2019 { - if !c.AssertContent { - s.decoder = nil - s.mediaType = nil - s.ContentSchema = nil - } - if c.ExtractAnnotations { - if deprecated, ok := m["deprecated"]; ok { - s.Deprecated = deprecated.(bool) - } - } - } - - for name, ext := range c.extensions { - es, err := ext.compiler.Compile(CompilerContext{c, r, stack, res}, m) - if err != nil { - return err - } - if es != nil { - if s.Extensions == nil { - s.Extensions = make(map[string]ExtSchema) - } - s.Extensions[name] = es - } - } - - return nil -} - -func (c *Compiler) validateSchema(r *resource, v interface{}, vloc string) error { - validate := func(meta *Schema) error { - if meta == nil { - return nil - } - return meta.validateValue(v, vloc) - } - - if err := validate(r.draft.meta); err != nil { - return err - } - for _, ext := range c.extensions { - if err := validate(ext.meta); err != nil { - return err - } - } - return nil -} - -func toStrings(arr []interface{}) []string { - s := make([]string, len(arr)) - for i, v := range arr { - s[i] = v.(string) - } - return s -} - -// SchemaRef captures schema and the path referring to it. -type schemaRef struct { - path string // relative-json-pointer to schema - schema *Schema // target schema - discard bool // true when scope left -} - -func (sr schemaRef) String() string { - return fmt.Sprintf("(%s)%v", sr.path, sr.schema) -} - -func checkLoop(stack []schemaRef, sref schemaRef) error { - for _, ref := range stack { - if ref.schema == sref.schema { - return infiniteLoopError(stack, sref) - } - } - return nil -} - -func keywordLocation(stack []schemaRef, path string) string { - var loc string - for _, ref := range stack[1:] { - loc += "/" + ref.path - } - if path != "" { - loc = loc + "/" + path - } - return loc -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v5/content.go b/vendor/github.com/santhosh-tekuri/jsonschema/v5/content.go deleted file mode 100644 index 7570b8b5a..000000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/v5/content.go +++ /dev/null @@ -1,29 +0,0 @@ -package jsonschema - -import ( - "encoding/base64" - "encoding/json" -) - -// Decoders is a registry of functions, which know how to decode -// string encoded in specific format. -// -// New Decoders can be registered by adding to this map. Key is encoding name, -// value is function that knows how to decode string in that format. -var Decoders = map[string]func(string) ([]byte, error){ - "base64": base64.StdEncoding.DecodeString, -} - -// MediaTypes is a registry of functions, which know how to validate -// whether the bytes represent data of that mediaType. -// -// New mediaTypes can be registered by adding to this map. Key is mediaType name, -// value is function that knows how to validate that mediaType. -var MediaTypes = map[string]func([]byte) error{ - "application/json": validateJSON, -} - -func validateJSON(b []byte) error { - var v interface{} - return json.Unmarshal(b, &v) -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v5/doc.go b/vendor/github.com/santhosh-tekuri/jsonschema/v5/doc.go deleted file mode 100644 index a124262a5..000000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/v5/doc.go +++ /dev/null @@ -1,49 +0,0 @@ -/* -Package jsonschema provides json-schema compilation and validation. - -Features: - - implements draft 2020-12, 2019-09, draft-7, draft-6, draft-4 - - fully compliant with JSON-Schema-Test-Suite, (excluding some optional) - - list of optional tests that are excluded can be found in schema_test.go(variable skipTests) - - validates schemas against meta-schema - - full support of remote references - - support of recursive references between schemas - - detects infinite loop in schemas - - thread safe validation - - rich, intuitive hierarchial error messages with json-pointers to exact location - - supports output formats flag, basic and detailed - - supports enabling format and content Assertions in draft2019-09 or above - - change Compiler.AssertFormat, Compiler.AssertContent to true - - compiled schema can be introspected. easier to develop tools like generating go structs given schema - - supports user-defined keywords via extensions - - implements following formats (supports user-defined) - - date-time, date, time, duration (supports leap-second) - - uuid, hostname, email - - ip-address, ipv4, ipv6 - - uri, uriref, uri-template(limited validation) - - json-pointer, relative-json-pointer - - regex, format - - implements following contentEncoding (supports user-defined) - - base64 - - implements following contentMediaType (supports user-defined) - - application/json - - can load from files/http/https/string/[]byte/io.Reader (supports user-defined) - -The schema is compiled against the version specified in "$schema" property. -If "$schema" property is missing, it uses latest draft which currently implemented -by this library. - -You can force to use specific draft, when "$schema" is missing, as follows: - - compiler := jsonschema.NewCompiler() - compiler.Draft = jsonschema.Draft4 - -This package supports loading json-schema from filePath and fileURL. - -To load json-schema from HTTPURL, add following import: - - import _ "github.com/santhosh-tekuri/jsonschema/v5/httploader" - -you can validate yaml documents. see https://play.golang.org/p/sJy1qY7dXgA -*/ -package jsonschema diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v5/draft.go b/vendor/github.com/santhosh-tekuri/jsonschema/v5/draft.go deleted file mode 100644 index 154fa5837..000000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/v5/draft.go +++ /dev/null @@ -1,1454 +0,0 @@ -package jsonschema - -import ( - "fmt" - "strconv" - "strings" -) - -// A Draft represents json-schema draft -type Draft struct { - version int - meta *Schema - id string // property name used to represent schema id. - boolSchema bool // is boolean valid schema - vocab []string // built-in vocab - defaultVocab []string // vocabs when $vocabulary is not used - subschemas map[string]position -} - -func (d *Draft) URL() string { - switch d.version { - case 2020: - return "https://json-schema.org/draft/2020-12/schema" - case 2019: - return "https://json-schema.org/draft/2019-09/schema" - case 7: - return "https://json-schema.org/draft-07/schema" - case 6: - return "https://json-schema.org/draft-06/schema" - case 4: - return "https://json-schema.org/draft-04/schema" - } - return "" -} - -func (d *Draft) String() string { - return fmt.Sprintf("Draft%d", d.version) -} - -func (d *Draft) loadMeta(url, schema string) { - c := NewCompiler() - c.AssertFormat = true - if err := c.AddResource(url, strings.NewReader(schema)); err != nil { - panic(err) - } - d.meta = c.MustCompile(url) - d.meta.meta = d.meta -} - -func (d *Draft) getID(sch interface{}) string { - m, ok := sch.(map[string]interface{}) - if !ok { - return "" - } - if _, ok := m["$ref"]; ok && d.version <= 7 { - // $ref prevents a sibling id from changing the base uri - return "" - } - v, ok := m[d.id] - if !ok { - return "" - } - id, ok := v.(string) - if !ok { - return "" - } - return id -} - -func (d *Draft) resolveID(base string, sch interface{}) (string, error) { - id, _ := split(d.getID(sch)) // strip fragment - if id == "" { - return "", nil - } - url, err := resolveURL(base, id) - url, _ = split(url) // strip fragment - return url, err -} - -func (d *Draft) anchors(sch interface{}) []string { - m, ok := sch.(map[string]interface{}) - if !ok { - return nil - } - - var anchors []string - - // before draft2019, anchor is specified in id - _, f := split(d.getID(m)) - if f != "#" { - anchors = append(anchors, f[1:]) - } - - if v, ok := m["$anchor"]; ok && d.version >= 2019 { - anchors = append(anchors, v.(string)) - } - if v, ok := m["$dynamicAnchor"]; ok && d.version >= 2020 { - anchors = append(anchors, v.(string)) - } - return anchors -} - -// listSubschemas collects subschemas in r into rr. -func (d *Draft) listSubschemas(r *resource, base string, rr map[string]*resource) error { - add := func(loc string, sch interface{}) error { - url, err := d.resolveID(base, sch) - if err != nil { - return err - } - floc := r.floc + "/" + loc - sr := &resource{url: url, floc: floc, doc: sch} - rr[floc] = sr - - base := base - if url != "" { - base = url - } - return d.listSubschemas(sr, base, rr) - } - - sch, ok := r.doc.(map[string]interface{}) - if !ok { - return nil - } - for kw, pos := range d.subschemas { - v, ok := sch[kw] - if !ok { - continue - } - if pos&self != 0 { - switch v := v.(type) { - case map[string]interface{}: - if err := add(kw, v); err != nil { - return err - } - case bool: - if d.boolSchema { - if err := add(kw, v); err != nil { - return err - } - } - } - } - if pos&item != 0 { - if v, ok := v.([]interface{}); ok { - for i, item := range v { - if err := add(kw+"/"+strconv.Itoa(i), item); err != nil { - return err - } - } - } - } - if pos&prop != 0 { - if v, ok := v.(map[string]interface{}); ok { - for pname, pval := range v { - if err := add(kw+"/"+escape(pname), pval); err != nil { - return err - } - } - } - } - } - return nil -} - -// isVocab tells whether url is built-in vocab. -func (d *Draft) isVocab(url string) bool { - for _, v := range d.vocab { - if url == v { - return true - } - } - return false -} - -type position uint - -const ( - self position = 1 << iota - prop - item -) - -// supported drafts -var ( - Draft4 = &Draft{version: 4, id: "id", boolSchema: false} - Draft6 = &Draft{version: 6, id: "$id", boolSchema: true} - Draft7 = &Draft{version: 7, id: "$id", boolSchema: true} - Draft2019 = &Draft{ - version: 2019, - id: "$id", - boolSchema: true, - vocab: []string{ - "https://json-schema.org/draft/2019-09/vocab/core", - "https://json-schema.org/draft/2019-09/vocab/applicator", - "https://json-schema.org/draft/2019-09/vocab/validation", - "https://json-schema.org/draft/2019-09/vocab/meta-data", - "https://json-schema.org/draft/2019-09/vocab/format", - "https://json-schema.org/draft/2019-09/vocab/content", - }, - defaultVocab: []string{ - "https://json-schema.org/draft/2019-09/vocab/core", - "https://json-schema.org/draft/2019-09/vocab/applicator", - "https://json-schema.org/draft/2019-09/vocab/validation", - }, - } - Draft2020 = &Draft{ - version: 2020, - id: "$id", - boolSchema: true, - vocab: []string{ - "https://json-schema.org/draft/2020-12/vocab/core", - "https://json-schema.org/draft/2020-12/vocab/applicator", - "https://json-schema.org/draft/2020-12/vocab/unevaluated", - "https://json-schema.org/draft/2020-12/vocab/validation", - "https://json-schema.org/draft/2020-12/vocab/meta-data", - "https://json-schema.org/draft/2020-12/vocab/format-annotation", - "https://json-schema.org/draft/2020-12/vocab/format-assertion", - "https://json-schema.org/draft/2020-12/vocab/content", - }, - defaultVocab: []string{ - "https://json-schema.org/draft/2020-12/vocab/core", - "https://json-schema.org/draft/2020-12/vocab/applicator", - "https://json-schema.org/draft/2020-12/vocab/unevaluated", - "https://json-schema.org/draft/2020-12/vocab/validation", - }, - } - - latest = Draft2020 -) - -func findDraft(url string) *Draft { - if strings.HasPrefix(url, "http://") { - url = "https://" + strings.TrimPrefix(url, "http://") - } - if strings.HasSuffix(url, "#") || strings.HasSuffix(url, "#/") { - url = url[:strings.IndexByte(url, '#')] - } - switch url { - case "https://json-schema.org/schema": - return latest - case "https://json-schema.org/draft/2020-12/schema": - return Draft2020 - case "https://json-schema.org/draft/2019-09/schema": - return Draft2019 - case "https://json-schema.org/draft-07/schema": - return Draft7 - case "https://json-schema.org/draft-06/schema": - return Draft6 - case "https://json-schema.org/draft-04/schema": - return Draft4 - } - return nil -} - -func init() { - subschemas := map[string]position{ - // type agnostic - "definitions": prop, - "not": self, - "allOf": item, - "anyOf": item, - "oneOf": item, - // object - "properties": prop, - "additionalProperties": self, - "patternProperties": prop, - // array - "items": self | item, - "additionalItems": self, - "dependencies": prop, - } - Draft4.subschemas = clone(subschemas) - - subschemas["propertyNames"] = self - subschemas["contains"] = self - Draft6.subschemas = clone(subschemas) - - subschemas["if"] = self - subschemas["then"] = self - subschemas["else"] = self - Draft7.subschemas = clone(subschemas) - - subschemas["$defs"] = prop - subschemas["dependentSchemas"] = prop - subschemas["unevaluatedProperties"] = self - subschemas["unevaluatedItems"] = self - subschemas["contentSchema"] = self - Draft2019.subschemas = clone(subschemas) - - subschemas["prefixItems"] = item - Draft2020.subschemas = clone(subschemas) - - Draft4.loadMeta("http://json-schema.org/draft-04/schema", `{ - "$schema": "http://json-schema.org/draft-04/schema#", - "description": "Core schema meta-schema", - "definitions": { - "schemaArray": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#" } - }, - "positiveInteger": { - "type": "integer", - "minimum": 0 - }, - "positiveIntegerDefault0": { - "allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ] - }, - "simpleTypes": { - "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ] - }, - "stringArray": { - "type": "array", - "items": { "type": "string" }, - "minItems": 1, - "uniqueItems": true - } - }, - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uriref" - }, - "$schema": { - "type": "string", - "format": "uri" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "default": {}, - "multipleOf": { - "type": "number", - "minimum": 0, - "exclusiveMinimum": true - }, - "maximum": { - "type": "number" - }, - "exclusiveMaximum": { - "type": "boolean", - "default": false - }, - "minimum": { - "type": "number" - }, - "exclusiveMinimum": { - "type": "boolean", - "default": false - }, - "maxLength": { "$ref": "#/definitions/positiveInteger" }, - "minLength": { "$ref": "#/definitions/positiveIntegerDefault0" }, - "pattern": { - "type": "string", - "format": "regex" - }, - "additionalItems": { - "anyOf": [ - { "type": "boolean" }, - { "$ref": "#" } - ], - "default": {} - }, - "items": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/schemaArray" } - ], - "default": {} - }, - "maxItems": { "$ref": "#/definitions/positiveInteger" }, - "minItems": { "$ref": "#/definitions/positiveIntegerDefault0" }, - "uniqueItems": { - "type": "boolean", - "default": false - }, - "maxProperties": { "$ref": "#/definitions/positiveInteger" }, - "minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" }, - "required": { "$ref": "#/definitions/stringArray" }, - "additionalProperties": { - "anyOf": [ - { "type": "boolean" }, - { "$ref": "#" } - ], - "default": {} - }, - "definitions": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "properties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "patternProperties": { - "type": "object", - "regexProperties": true, - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "regexProperties": { "type": "boolean" }, - "dependencies": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/stringArray" } - ] - } - }, - "enum": { - "type": "array", - "minItems": 1, - "uniqueItems": true - }, - "type": { - "anyOf": [ - { "$ref": "#/definitions/simpleTypes" }, - { - "type": "array", - "items": { "$ref": "#/definitions/simpleTypes" }, - "minItems": 1, - "uniqueItems": true - } - ] - }, - "allOf": { "$ref": "#/definitions/schemaArray" }, - "anyOf": { "$ref": "#/definitions/schemaArray" }, - "oneOf": { "$ref": "#/definitions/schemaArray" }, - "not": { "$ref": "#" }, - "format": { "type": "string" }, - "$ref": { "type": "string" } - }, - "dependencies": { - "exclusiveMaximum": [ "maximum" ], - "exclusiveMinimum": [ "minimum" ] - }, - "default": {} - }`) - Draft6.loadMeta("http://json-schema.org/draft-06/schema", `{ - "$schema": "http://json-schema.org/draft-06/schema#", - "$id": "http://json-schema.org/draft-06/schema#", - "title": "Core schema meta-schema", - "definitions": { - "schemaArray": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#" } - }, - "nonNegativeInteger": { - "type": "integer", - "minimum": 0 - }, - "nonNegativeIntegerDefault0": { - "allOf": [ - { "$ref": "#/definitions/nonNegativeInteger" }, - { "default": 0 } - ] - }, - "simpleTypes": { - "enum": [ - "array", - "boolean", - "integer", - "null", - "number", - "object", - "string" - ] - }, - "stringArray": { - "type": "array", - "items": { "type": "string" }, - "uniqueItems": true, - "default": [] - } - }, - "type": ["object", "boolean"], - "properties": { - "$id": { - "type": "string", - "format": "uri-reference" - }, - "$schema": { - "type": "string", - "format": "uri" - }, - "$ref": { - "type": "string", - "format": "uri-reference" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "default": {}, - "multipleOf": { - "type": "number", - "exclusiveMinimum": 0 - }, - "maximum": { - "type": "number" - }, - "exclusiveMaximum": { - "type": "number" - }, - "minimum": { - "type": "number" - }, - "exclusiveMinimum": { - "type": "number" - }, - "maxLength": { "$ref": "#/definitions/nonNegativeInteger" }, - "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "pattern": { - "type": "string", - "format": "regex" - }, - "additionalItems": { "$ref": "#" }, - "items": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/schemaArray" } - ], - "default": {} - }, - "maxItems": { "$ref": "#/definitions/nonNegativeInteger" }, - "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "uniqueItems": { - "type": "boolean", - "default": false - }, - "contains": { "$ref": "#" }, - "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" }, - "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "required": { "$ref": "#/definitions/stringArray" }, - "additionalProperties": { "$ref": "#" }, - "definitions": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "properties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "patternProperties": { - "type": "object", - "regexProperties": true, - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "dependencies": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/stringArray" } - ] - } - }, - "propertyNames": { "$ref": "#" }, - "const": {}, - "enum": { - "type": "array", - "minItems": 1, - "uniqueItems": true - }, - "type": { - "anyOf": [ - { "$ref": "#/definitions/simpleTypes" }, - { - "type": "array", - "items": { "$ref": "#/definitions/simpleTypes" }, - "minItems": 1, - "uniqueItems": true - } - ] - }, - "format": { "type": "string" }, - "allOf": { "$ref": "#/definitions/schemaArray" }, - "anyOf": { "$ref": "#/definitions/schemaArray" }, - "oneOf": { "$ref": "#/definitions/schemaArray" }, - "not": { "$ref": "#" } - }, - "default": {} - }`) - Draft7.loadMeta("http://json-schema.org/draft-07/schema", `{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "http://json-schema.org/draft-07/schema#", - "title": "Core schema meta-schema", - "definitions": { - "schemaArray": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#" } - }, - "nonNegativeInteger": { - "type": "integer", - "minimum": 0 - }, - "nonNegativeIntegerDefault0": { - "allOf": [ - { "$ref": "#/definitions/nonNegativeInteger" }, - { "default": 0 } - ] - }, - "simpleTypes": { - "enum": [ - "array", - "boolean", - "integer", - "null", - "number", - "object", - "string" - ] - }, - "stringArray": { - "type": "array", - "items": { "type": "string" }, - "uniqueItems": true, - "default": [] - } - }, - "type": ["object", "boolean"], - "properties": { - "$id": { - "type": "string", - "format": "uri-reference" - }, - "$schema": { - "type": "string", - "format": "uri" - }, - "$ref": { - "type": "string", - "format": "uri-reference" - }, - "$comment": { - "type": "string" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "default": true, - "readOnly": { - "type": "boolean", - "default": false - }, - "writeOnly": { - "type": "boolean", - "default": false - }, - "examples": { - "type": "array", - "items": true - }, - "multipleOf": { - "type": "number", - "exclusiveMinimum": 0 - }, - "maximum": { - "type": "number" - }, - "exclusiveMaximum": { - "type": "number" - }, - "minimum": { - "type": "number" - }, - "exclusiveMinimum": { - "type": "number" - }, - "maxLength": { "$ref": "#/definitions/nonNegativeInteger" }, - "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "pattern": { - "type": "string", - "format": "regex" - }, - "additionalItems": { "$ref": "#" }, - "items": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/schemaArray" } - ], - "default": true - }, - "maxItems": { "$ref": "#/definitions/nonNegativeInteger" }, - "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "uniqueItems": { - "type": "boolean", - "default": false - }, - "contains": { "$ref": "#" }, - "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" }, - "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "required": { "$ref": "#/definitions/stringArray" }, - "additionalProperties": { "$ref": "#" }, - "definitions": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "properties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "patternProperties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "propertyNames": { "format": "regex" }, - "default": {} - }, - "dependencies": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/stringArray" } - ] - } - }, - "propertyNames": { "$ref": "#" }, - "const": true, - "enum": { - "type": "array", - "items": true, - "minItems": 1, - "uniqueItems": true - }, - "type": { - "anyOf": [ - { "$ref": "#/definitions/simpleTypes" }, - { - "type": "array", - "items": { "$ref": "#/definitions/simpleTypes" }, - "minItems": 1, - "uniqueItems": true - } - ] - }, - "format": { "type": "string" }, - "contentMediaType": { "type": "string" }, - "contentEncoding": { "type": "string" }, - "if": { "$ref": "#" }, - "then": { "$ref": "#" }, - "else": { "$ref": "#" }, - "allOf": { "$ref": "#/definitions/schemaArray" }, - "anyOf": { "$ref": "#/definitions/schemaArray" }, - "oneOf": { "$ref": "#/definitions/schemaArray" }, - "not": { "$ref": "#" } - }, - "default": true - }`) - Draft2019.loadMeta("https://json-schema.org/draft/2019-09/schema", `{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://json-schema.org/draft/2019-09/schema", - "$vocabulary": { - "https://json-schema.org/draft/2019-09/vocab/core": true, - "https://json-schema.org/draft/2019-09/vocab/applicator": true, - "https://json-schema.org/draft/2019-09/vocab/validation": true, - "https://json-schema.org/draft/2019-09/vocab/meta-data": true, - "https://json-schema.org/draft/2019-09/vocab/format": false, - "https://json-schema.org/draft/2019-09/vocab/content": true - }, - "$recursiveAnchor": true, - - "title": "Core and Validation specifications meta-schema", - "allOf": [ - {"$ref": "meta/core"}, - {"$ref": "meta/applicator"}, - {"$ref": "meta/validation"}, - {"$ref": "meta/meta-data"}, - {"$ref": "meta/format"}, - {"$ref": "meta/content"} - ], - "type": ["object", "boolean"], - "properties": { - "definitions": { - "$comment": "While no longer an official keyword as it is replaced by $defs, this keyword is retained in the meta-schema to prevent incompatible extensions as it remains in common use.", - "type": "object", - "additionalProperties": { "$recursiveRef": "#" }, - "default": {} - }, - "dependencies": { - "$comment": "\"dependencies\" is no longer a keyword, but schema authors should avoid redefining it to facilitate a smooth transition to \"dependentSchemas\" and \"dependentRequired\"", - "type": "object", - "additionalProperties": { - "anyOf": [ - { "$recursiveRef": "#" }, - { "$ref": "meta/validation#/$defs/stringArray" } - ] - } - } - } - }`) - Draft2020.loadMeta("https://json-schema.org/draft/2020-12/schema", `{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://json-schema.org/draft/2020-12/schema", - "$vocabulary": { - "https://json-schema.org/draft/2020-12/vocab/core": true, - "https://json-schema.org/draft/2020-12/vocab/applicator": true, - "https://json-schema.org/draft/2020-12/vocab/unevaluated": true, - "https://json-schema.org/draft/2020-12/vocab/validation": true, - "https://json-schema.org/draft/2020-12/vocab/meta-data": true, - "https://json-schema.org/draft/2020-12/vocab/format-annotation": true, - "https://json-schema.org/draft/2020-12/vocab/content": true - }, - "$dynamicAnchor": "meta", - - "title": "Core and Validation specifications meta-schema", - "allOf": [ - {"$ref": "meta/core"}, - {"$ref": "meta/applicator"}, - {"$ref": "meta/unevaluated"}, - {"$ref": "meta/validation"}, - {"$ref": "meta/meta-data"}, - {"$ref": "meta/format-annotation"}, - {"$ref": "meta/content"} - ], - "type": ["object", "boolean"], - "$comment": "This meta-schema also defines keywords that have appeared in previous drafts in order to prevent incompatible extensions as they remain in common use.", - "properties": { - "definitions": { - "$comment": "\"definitions\" has been replaced by \"$defs\".", - "type": "object", - "additionalProperties": { "$dynamicRef": "#meta" }, - "deprecated": true, - "default": {} - }, - "dependencies": { - "$comment": "\"dependencies\" has been split and replaced by \"dependentSchemas\" and \"dependentRequired\" in order to serve their differing semantics.", - "type": "object", - "additionalProperties": { - "anyOf": [ - { "$dynamicRef": "#meta" }, - { "$ref": "meta/validation#/$defs/stringArray" } - ] - }, - "deprecated": true, - "default": {} - }, - "$recursiveAnchor": { - "$comment": "\"$recursiveAnchor\" has been replaced by \"$dynamicAnchor\".", - "$ref": "meta/core#/$defs/anchorString", - "deprecated": true - }, - "$recursiveRef": { - "$comment": "\"$recursiveRef\" has been replaced by \"$dynamicRef\".", - "$ref": "meta/core#/$defs/uriReferenceString", - "deprecated": true - } - } - }`) -} - -var vocabSchemas = map[string]string{ - "https://json-schema.org/draft/2019-09/meta/core": `{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://json-schema.org/draft/2019-09/meta/core", - "$vocabulary": { - "https://json-schema.org/draft/2019-09/vocab/core": true - }, - "$recursiveAnchor": true, - - "title": "Core vocabulary meta-schema", - "type": ["object", "boolean"], - "properties": { - "$id": { - "type": "string", - "format": "uri-reference", - "$comment": "Non-empty fragments not allowed.", - "pattern": "^[^#]*#?$" - }, - "$schema": { - "type": "string", - "format": "uri" - }, - "$anchor": { - "type": "string", - "pattern": "^[A-Za-z][-A-Za-z0-9.:_]*$" - }, - "$ref": { - "type": "string", - "format": "uri-reference" - }, - "$recursiveRef": { - "type": "string", - "format": "uri-reference" - }, - "$recursiveAnchor": { - "type": "boolean", - "default": false - }, - "$vocabulary": { - "type": "object", - "propertyNames": { - "type": "string", - "format": "uri" - }, - "additionalProperties": { - "type": "boolean" - } - }, - "$comment": { - "type": "string" - }, - "$defs": { - "type": "object", - "additionalProperties": { "$recursiveRef": "#" }, - "default": {} - } - } - }`, - "https://json-schema.org/draft/2019-09/meta/applicator": `{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://json-schema.org/draft/2019-09/meta/applicator", - "$vocabulary": { - "https://json-schema.org/draft/2019-09/vocab/applicator": true - }, - "$recursiveAnchor": true, - - "title": "Applicator vocabulary meta-schema", - "type": ["object", "boolean"], - "properties": { - "additionalItems": { "$recursiveRef": "#" }, - "unevaluatedItems": { "$recursiveRef": "#" }, - "items": { - "anyOf": [ - { "$recursiveRef": "#" }, - { "$ref": "#/$defs/schemaArray" } - ] - }, - "contains": { "$recursiveRef": "#" }, - "additionalProperties": { "$recursiveRef": "#" }, - "unevaluatedProperties": { "$recursiveRef": "#" }, - "properties": { - "type": "object", - "additionalProperties": { "$recursiveRef": "#" }, - "default": {} - }, - "patternProperties": { - "type": "object", - "additionalProperties": { "$recursiveRef": "#" }, - "propertyNames": { "format": "regex" }, - "default": {} - }, - "dependentSchemas": { - "type": "object", - "additionalProperties": { - "$recursiveRef": "#" - } - }, - "propertyNames": { "$recursiveRef": "#" }, - "if": { "$recursiveRef": "#" }, - "then": { "$recursiveRef": "#" }, - "else": { "$recursiveRef": "#" }, - "allOf": { "$ref": "#/$defs/schemaArray" }, - "anyOf": { "$ref": "#/$defs/schemaArray" }, - "oneOf": { "$ref": "#/$defs/schemaArray" }, - "not": { "$recursiveRef": "#" } - }, - "$defs": { - "schemaArray": { - "type": "array", - "minItems": 1, - "items": { "$recursiveRef": "#" } - } - } - }`, - "https://json-schema.org/draft/2019-09/meta/validation": `{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://json-schema.org/draft/2019-09/meta/validation", - "$vocabulary": { - "https://json-schema.org/draft/2019-09/vocab/validation": true - }, - "$recursiveAnchor": true, - - "title": "Validation vocabulary meta-schema", - "type": ["object", "boolean"], - "properties": { - "multipleOf": { - "type": "number", - "exclusiveMinimum": 0 - }, - "maximum": { - "type": "number" - }, - "exclusiveMaximum": { - "type": "number" - }, - "minimum": { - "type": "number" - }, - "exclusiveMinimum": { - "type": "number" - }, - "maxLength": { "$ref": "#/$defs/nonNegativeInteger" }, - "minLength": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, - "pattern": { - "type": "string", - "format": "regex" - }, - "maxItems": { "$ref": "#/$defs/nonNegativeInteger" }, - "minItems": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, - "uniqueItems": { - "type": "boolean", - "default": false - }, - "maxContains": { "$ref": "#/$defs/nonNegativeInteger" }, - "minContains": { - "$ref": "#/$defs/nonNegativeInteger", - "default": 1 - }, - "maxProperties": { "$ref": "#/$defs/nonNegativeInteger" }, - "minProperties": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, - "required": { "$ref": "#/$defs/stringArray" }, - "dependentRequired": { - "type": "object", - "additionalProperties": { - "$ref": "#/$defs/stringArray" - } - }, - "const": true, - "enum": { - "type": "array", - "items": true - }, - "type": { - "anyOf": [ - { "$ref": "#/$defs/simpleTypes" }, - { - "type": "array", - "items": { "$ref": "#/$defs/simpleTypes" }, - "minItems": 1, - "uniqueItems": true - } - ] - } - }, - "$defs": { - "nonNegativeInteger": { - "type": "integer", - "minimum": 0 - }, - "nonNegativeIntegerDefault0": { - "$ref": "#/$defs/nonNegativeInteger", - "default": 0 - }, - "simpleTypes": { - "enum": [ - "array", - "boolean", - "integer", - "null", - "number", - "object", - "string" - ] - }, - "stringArray": { - "type": "array", - "items": { "type": "string" }, - "uniqueItems": true, - "default": [] - } - } - }`, - "https://json-schema.org/draft/2019-09/meta/meta-data": `{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://json-schema.org/draft/2019-09/meta/meta-data", - "$vocabulary": { - "https://json-schema.org/draft/2019-09/vocab/meta-data": true - }, - "$recursiveAnchor": true, - - "title": "Meta-data vocabulary meta-schema", - - "type": ["object", "boolean"], - "properties": { - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "default": true, - "deprecated": { - "type": "boolean", - "default": false - }, - "readOnly": { - "type": "boolean", - "default": false - }, - "writeOnly": { - "type": "boolean", - "default": false - }, - "examples": { - "type": "array", - "items": true - } - } - }`, - "https://json-schema.org/draft/2019-09/meta/format": `{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://json-schema.org/draft/2019-09/meta/format", - "$vocabulary": { - "https://json-schema.org/draft/2019-09/vocab/format": true - }, - "$recursiveAnchor": true, - - "title": "Format vocabulary meta-schema", - "type": ["object", "boolean"], - "properties": { - "format": { "type": "string" } - } - }`, - "https://json-schema.org/draft/2019-09/meta/content": `{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://json-schema.org/draft/2019-09/meta/content", - "$vocabulary": { - "https://json-schema.org/draft/2019-09/vocab/content": true - }, - "$recursiveAnchor": true, - - "title": "Content vocabulary meta-schema", - - "type": ["object", "boolean"], - "properties": { - "contentMediaType": { "type": "string" }, - "contentEncoding": { "type": "string" }, - "contentSchema": { "$recursiveRef": "#" } - } - }`, - "https://json-schema.org/draft/2020-12/meta/core": `{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://json-schema.org/draft/2020-12/meta/core", - "$vocabulary": { - "https://json-schema.org/draft/2020-12/vocab/core": true - }, - "$dynamicAnchor": "meta", - - "title": "Core vocabulary meta-schema", - "type": ["object", "boolean"], - "properties": { - "$id": { - "$ref": "#/$defs/uriReferenceString", - "$comment": "Non-empty fragments not allowed.", - "pattern": "^[^#]*#?$" - }, - "$schema": { "$ref": "#/$defs/uriString" }, - "$ref": { "$ref": "#/$defs/uriReferenceString" }, - "$anchor": { "$ref": "#/$defs/anchorString" }, - "$dynamicRef": { "$ref": "#/$defs/uriReferenceString" }, - "$dynamicAnchor": { "$ref": "#/$defs/anchorString" }, - "$vocabulary": { - "type": "object", - "propertyNames": { "$ref": "#/$defs/uriString" }, - "additionalProperties": { - "type": "boolean" - } - }, - "$comment": { - "type": "string" - }, - "$defs": { - "type": "object", - "additionalProperties": { "$dynamicRef": "#meta" } - } - }, - "$defs": { - "anchorString": { - "type": "string", - "pattern": "^[A-Za-z_][-A-Za-z0-9._]*$" - }, - "uriString": { - "type": "string", - "format": "uri" - }, - "uriReferenceString": { - "type": "string", - "format": "uri-reference" - } - } - }`, - "https://json-schema.org/draft/2020-12/meta/applicator": `{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://json-schema.org/draft/2020-12/meta/applicator", - "$vocabulary": { - "https://json-schema.org/draft/2020-12/vocab/applicator": true - }, - "$dynamicAnchor": "meta", - - "title": "Applicator vocabulary meta-schema", - "type": ["object", "boolean"], - "properties": { - "prefixItems": { "$ref": "#/$defs/schemaArray" }, - "items": { "$dynamicRef": "#meta" }, - "contains": { "$dynamicRef": "#meta" }, - "additionalProperties": { "$dynamicRef": "#meta" }, - "properties": { - "type": "object", - "additionalProperties": { "$dynamicRef": "#meta" }, - "default": {} - }, - "patternProperties": { - "type": "object", - "additionalProperties": { "$dynamicRef": "#meta" }, - "propertyNames": { "format": "regex" }, - "default": {} - }, - "dependentSchemas": { - "type": "object", - "additionalProperties": { "$dynamicRef": "#meta" }, - "default": {} - }, - "propertyNames": { "$dynamicRef": "#meta" }, - "if": { "$dynamicRef": "#meta" }, - "then": { "$dynamicRef": "#meta" }, - "else": { "$dynamicRef": "#meta" }, - "allOf": { "$ref": "#/$defs/schemaArray" }, - "anyOf": { "$ref": "#/$defs/schemaArray" }, - "oneOf": { "$ref": "#/$defs/schemaArray" }, - "not": { "$dynamicRef": "#meta" } - }, - "$defs": { - "schemaArray": { - "type": "array", - "minItems": 1, - "items": { "$dynamicRef": "#meta" } - } - } - }`, - "https://json-schema.org/draft/2020-12/meta/unevaluated": `{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://json-schema.org/draft/2020-12/meta/unevaluated", - "$vocabulary": { - "https://json-schema.org/draft/2020-12/vocab/unevaluated": true - }, - "$dynamicAnchor": "meta", - - "title": "Unevaluated applicator vocabulary meta-schema", - "type": ["object", "boolean"], - "properties": { - "unevaluatedItems": { "$dynamicRef": "#meta" }, - "unevaluatedProperties": { "$dynamicRef": "#meta" } - } - }`, - "https://json-schema.org/draft/2020-12/meta/validation": `{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://json-schema.org/draft/2020-12/meta/validation", - "$vocabulary": { - "https://json-schema.org/draft/2020-12/vocab/validation": true - }, - "$dynamicAnchor": "meta", - - "title": "Validation vocabulary meta-schema", - "type": ["object", "boolean"], - "properties": { - "type": { - "anyOf": [ - { "$ref": "#/$defs/simpleTypes" }, - { - "type": "array", - "items": { "$ref": "#/$defs/simpleTypes" }, - "minItems": 1, - "uniqueItems": true - } - ] - }, - "const": true, - "enum": { - "type": "array", - "items": true - }, - "multipleOf": { - "type": "number", - "exclusiveMinimum": 0 - }, - "maximum": { - "type": "number" - }, - "exclusiveMaximum": { - "type": "number" - }, - "minimum": { - "type": "number" - }, - "exclusiveMinimum": { - "type": "number" - }, - "maxLength": { "$ref": "#/$defs/nonNegativeInteger" }, - "minLength": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, - "pattern": { - "type": "string", - "format": "regex" - }, - "maxItems": { "$ref": "#/$defs/nonNegativeInteger" }, - "minItems": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, - "uniqueItems": { - "type": "boolean", - "default": false - }, - "maxContains": { "$ref": "#/$defs/nonNegativeInteger" }, - "minContains": { - "$ref": "#/$defs/nonNegativeInteger", - "default": 1 - }, - "maxProperties": { "$ref": "#/$defs/nonNegativeInteger" }, - "minProperties": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, - "required": { "$ref": "#/$defs/stringArray" }, - "dependentRequired": { - "type": "object", - "additionalProperties": { - "$ref": "#/$defs/stringArray" - } - } - }, - "$defs": { - "nonNegativeInteger": { - "type": "integer", - "minimum": 0 - }, - "nonNegativeIntegerDefault0": { - "$ref": "#/$defs/nonNegativeInteger", - "default": 0 - }, - "simpleTypes": { - "enum": [ - "array", - "boolean", - "integer", - "null", - "number", - "object", - "string" - ] - }, - "stringArray": { - "type": "array", - "items": { "type": "string" }, - "uniqueItems": true, - "default": [] - } - } - }`, - "https://json-schema.org/draft/2020-12/meta/meta-data": `{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://json-schema.org/draft/2020-12/meta/meta-data", - "$vocabulary": { - "https://json-schema.org/draft/2020-12/vocab/meta-data": true - }, - "$dynamicAnchor": "meta", - - "title": "Meta-data vocabulary meta-schema", - - "type": ["object", "boolean"], - "properties": { - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "default": true, - "deprecated": { - "type": "boolean", - "default": false - }, - "readOnly": { - "type": "boolean", - "default": false - }, - "writeOnly": { - "type": "boolean", - "default": false - }, - "examples": { - "type": "array", - "items": true - } - } - }`, - "https://json-schema.org/draft/2020-12/meta/format-annotation": `{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://json-schema.org/draft/2020-12/meta/format-annotation", - "$vocabulary": { - "https://json-schema.org/draft/2020-12/vocab/format-annotation": true - }, - "$dynamicAnchor": "meta", - - "title": "Format vocabulary meta-schema for annotation results", - "type": ["object", "boolean"], - "properties": { - "format": { "type": "string" } - } - }`, - "https://json-schema.org/draft/2020-12/meta/format-assertion": `{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://json-schema.org/draft/2020-12/meta/format-assertion", - "$vocabulary": { - "https://json-schema.org/draft/2020-12/vocab/format-assertion": true - }, - "$dynamicAnchor": "meta", - - "title": "Format vocabulary meta-schema for assertion results", - "type": ["object", "boolean"], - "properties": { - "format": { "type": "string" } - } - }`, - "https://json-schema.org/draft/2020-12/meta/content": `{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://json-schema.org/draft/2020-12/meta/content", - "$vocabulary": { - "https://json-schema.org/draft/2020-12/vocab/content": true - }, - "$dynamicAnchor": "meta", - - "title": "Content vocabulary meta-schema", - - "type": ["object", "boolean"], - "properties": { - "contentEncoding": { "type": "string" }, - "contentMediaType": { "type": "string" }, - "contentSchema": { "$dynamicRef": "#meta" } - } - }`, -} - -func clone(m map[string]position) map[string]position { - mm := make(map[string]position) - for k, v := range m { - mm[k] = v - } - return mm -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v5/errors.go b/vendor/github.com/santhosh-tekuri/jsonschema/v5/errors.go deleted file mode 100644 index deaded89f..000000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/v5/errors.go +++ /dev/null @@ -1,129 +0,0 @@ -package jsonschema - -import ( - "fmt" - "strings" -) - -// InvalidJSONTypeError is the error type returned by ValidateInterface. -// this tells that specified go object is not valid jsonType. -type InvalidJSONTypeError string - -func (e InvalidJSONTypeError) Error() string { - return fmt.Sprintf("jsonschema: invalid jsonType: %s", string(e)) -} - -// InfiniteLoopError is returned by Compile/Validate. -// this gives url#keywordLocation that lead to infinity loop. -type InfiniteLoopError string - -func (e InfiniteLoopError) Error() string { - return "jsonschema: infinite loop " + string(e) -} - -func infiniteLoopError(stack []schemaRef, sref schemaRef) InfiniteLoopError { - var path string - for _, ref := range stack { - if path == "" { - path += ref.schema.Location - } else { - path += "/" + ref.path - } - } - return InfiniteLoopError(path + "/" + sref.path) -} - -// SchemaError is the error type returned by Compile. -type SchemaError struct { - // SchemaURL is the url to json-schema that filed to compile. - // This is helpful, if your schema refers to external schemas - SchemaURL string - - // Err is the error that occurred during compilation. - // It could be ValidationError, because compilation validates - // given schema against the json meta-schema - Err error -} - -func (se *SchemaError) Unwrap() error { - return se.Err -} - -func (se *SchemaError) Error() string { - s := fmt.Sprintf("jsonschema %s compilation failed", se.SchemaURL) - if se.Err != nil { - return fmt.Sprintf("%s: %v", s, strings.TrimPrefix(se.Err.Error(), "jsonschema: ")) - } - return s -} - -func (se *SchemaError) GoString() string { - if _, ok := se.Err.(*ValidationError); ok { - return fmt.Sprintf("jsonschema %s compilation failed\n%#v", se.SchemaURL, se.Err) - } - return se.Error() -} - -// ValidationError is the error type returned by Validate. -type ValidationError struct { - KeywordLocation string // validation path of validating keyword or schema - AbsoluteKeywordLocation string // absolute location of validating keyword or schema - InstanceLocation string // location of the json value within the instance being validated - Message string // describes error - Causes []*ValidationError // nested validation errors -} - -func (ve *ValidationError) add(causes ...error) error { - for _, cause := range causes { - ve.Causes = append(ve.Causes, cause.(*ValidationError)) - } - return ve -} - -func (ve *ValidationError) causes(err error) error { - if err := err.(*ValidationError); err.Message == "" { - ve.Causes = err.Causes - } else { - ve.add(err) - } - return ve -} - -func (ve *ValidationError) Error() string { - leaf := ve - for len(leaf.Causes) > 0 { - leaf = leaf.Causes[0] - } - u, _ := split(ve.AbsoluteKeywordLocation) - return fmt.Sprintf("jsonschema: %s does not validate with %s: %s", quote(leaf.InstanceLocation), u+"#"+leaf.KeywordLocation, leaf.Message) -} - -func (ve *ValidationError) GoString() string { - sloc := ve.AbsoluteKeywordLocation - sloc = sloc[strings.IndexByte(sloc, '#')+1:] - msg := fmt.Sprintf("[I#%s] [S#%s] %s", ve.InstanceLocation, sloc, ve.Message) - for _, c := range ve.Causes { - for _, line := range strings.Split(c.GoString(), "\n") { - msg += "\n " + line - } - } - return msg -} - -func joinPtr(ptr1, ptr2 string) string { - if len(ptr1) == 0 { - return ptr2 - } - if len(ptr2) == 0 { - return ptr1 - } - return ptr1 + "/" + ptr2 -} - -// quote returns single-quoted string -func quote(s string) string { - s = fmt.Sprintf("%q", s) - s = strings.ReplaceAll(s, `\"`, `"`) - s = strings.ReplaceAll(s, `'`, `\'`) - return "'" + s[1:len(s)-1] + "'" -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v5/extension.go b/vendor/github.com/santhosh-tekuri/jsonschema/v5/extension.go deleted file mode 100644 index 452ba118c..000000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/v5/extension.go +++ /dev/null @@ -1,116 +0,0 @@ -package jsonschema - -// ExtCompiler compiles custom keyword(s) into ExtSchema. -type ExtCompiler interface { - // Compile compiles the custom keywords in schema m and returns its compiled representation. - // if the schema m does not contain the keywords defined by this extension, - // compiled representation nil should be returned. - Compile(ctx CompilerContext, m map[string]interface{}) (ExtSchema, error) -} - -// ExtSchema is schema representation of custom keyword(s) -type ExtSchema interface { - // Validate validates the json value v with this ExtSchema. - // Returned error must be *ValidationError. - Validate(ctx ValidationContext, v interface{}) error -} - -type extension struct { - meta *Schema - compiler ExtCompiler -} - -// RegisterExtension registers custom keyword(s) into this compiler. -// -// name is extension name, used only to avoid name collisions. -// meta captures the metaschema for the new keywords. -// This is used to validate the schema before calling ext.Compile. -func (c *Compiler) RegisterExtension(name string, meta *Schema, ext ExtCompiler) { - c.extensions[name] = extension{meta, ext} -} - -// CompilerContext --- - -// CompilerContext provides additional context required in compiling for extension. -type CompilerContext struct { - c *Compiler - r *resource - stack []schemaRef - res *resource -} - -// Compile compiles given value at ptr into *Schema. This is useful in implementing -// keyword like allOf/not/patternProperties. -// -// schPath is the relative-json-pointer to the schema to be compiled from parent schema. -// -// applicableOnSameInstance tells whether current schema and the given schema -// are applied on same instance value. this is used to detect infinite loop in schema. -func (ctx CompilerContext) Compile(schPath string, applicableOnSameInstance bool) (*Schema, error) { - var stack []schemaRef - if applicableOnSameInstance { - stack = ctx.stack - } - return ctx.c.compileRef(ctx.r, stack, schPath, ctx.res, ctx.r.url+ctx.res.floc+"/"+schPath) -} - -// CompileRef compiles the schema referenced by ref uri -// -// refPath is the relative-json-pointer to ref. -// -// applicableOnSameInstance tells whether current schema and the given schema -// are applied on same instance value. this is used to detect infinite loop in schema. -func (ctx CompilerContext) CompileRef(ref string, refPath string, applicableOnSameInstance bool) (*Schema, error) { - var stack []schemaRef - if applicableOnSameInstance { - stack = ctx.stack - } - return ctx.c.compileRef(ctx.r, stack, refPath, ctx.res, ref) -} - -// ValidationContext --- - -// ValidationContext provides additional context required in validating for extension. -type ValidationContext struct { - result validationResult - validate func(sch *Schema, schPath string, v interface{}, vpath string) error - validateInplace func(sch *Schema, schPath string) error - validationError func(keywordPath string, format string, a ...interface{}) *ValidationError -} - -// EvaluatedProp marks given property of object as evaluated. -func (ctx ValidationContext) EvaluatedProp(prop string) { - delete(ctx.result.unevalProps, prop) -} - -// EvaluatedItem marks given index of array as evaluated. -func (ctx ValidationContext) EvaluatedItem(index int) { - delete(ctx.result.unevalItems, index) -} - -// Validate validates schema s with value v. Extension must use this method instead of -// *Schema.ValidateInterface method. This will be useful in implementing keywords like -// allOf/oneOf -// -// spath is relative-json-pointer to s -// vpath is relative-json-pointer to v. -func (ctx ValidationContext) Validate(s *Schema, spath string, v interface{}, vpath string) error { - if vpath == "" { - return ctx.validateInplace(s, spath) - } - return ctx.validate(s, spath, v, vpath) -} - -// Error used to construct validation error by extensions. -// -// keywordPath is relative-json-pointer to keyword. -func (ctx ValidationContext) Error(keywordPath string, format string, a ...interface{}) *ValidationError { - return ctx.validationError(keywordPath, format, a...) -} - -// Group is used by extensions to group multiple errors as causes to parent error. -// This is useful in implementing keywords like allOf where each schema specified -// in allOf can result a validationError. -func (ValidationError) Group(parent *ValidationError, causes ...error) error { - return parent.add(causes...) -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v5/format.go b/vendor/github.com/santhosh-tekuri/jsonschema/v5/format.go deleted file mode 100644 index 05686073f..000000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/v5/format.go +++ /dev/null @@ -1,567 +0,0 @@ -package jsonschema - -import ( - "errors" - "net" - "net/mail" - "net/url" - "regexp" - "strconv" - "strings" - "time" -) - -// Formats is a registry of functions, which know how to validate -// a specific format. -// -// New Formats can be registered by adding to this map. Key is format name, -// value is function that knows how to validate that format. -var Formats = map[string]func(interface{}) bool{ - "date-time": isDateTime, - "date": isDate, - "time": isTime, - "duration": isDuration, - "period": isPeriod, - "hostname": isHostname, - "email": isEmail, - "ip-address": isIPV4, - "ipv4": isIPV4, - "ipv6": isIPV6, - "uri": isURI, - "iri": isURI, - "uri-reference": isURIReference, - "uriref": isURIReference, - "iri-reference": isURIReference, - "uri-template": isURITemplate, - "regex": isRegex, - "json-pointer": isJSONPointer, - "relative-json-pointer": isRelativeJSONPointer, - "uuid": isUUID, -} - -// isDateTime tells whether given string is a valid date representation -// as defined by RFC 3339, section 5.6. -// -// see https://datatracker.ietf.org/doc/html/rfc3339#section-5.6, for details -func isDateTime(v interface{}) bool { - s, ok := v.(string) - if !ok { - return true - } - if len(s) < 20 { // yyyy-mm-ddThh:mm:ssZ - return false - } - if s[10] != 'T' && s[10] != 't' { - return false - } - return isDate(s[:10]) && isTime(s[11:]) -} - -// isDate tells whether given string is a valid full-date production -// as defined by RFC 3339, section 5.6. -// -// see https://datatracker.ietf.org/doc/html/rfc3339#section-5.6, for details -func isDate(v interface{}) bool { - s, ok := v.(string) - if !ok { - return true - } - _, err := time.Parse("2006-01-02", s) - return err == nil -} - -// isTime tells whether given string is a valid full-time production -// as defined by RFC 3339, section 5.6. -// -// see https://datatracker.ietf.org/doc/html/rfc3339#section-5.6, for details -func isTime(v interface{}) bool { - str, ok := v.(string) - if !ok { - return true - } - - // golang time package does not support leap seconds. - // so we are parsing it manually here. - - // hh:mm:ss - // 01234567 - if len(str) < 9 || str[2] != ':' || str[5] != ':' { - return false - } - isInRange := func(str string, min, max int) (int, bool) { - n, err := strconv.Atoi(str) - if err != nil { - return 0, false - } - if n < min || n > max { - return 0, false - } - return n, true - } - var h, m, s int - if h, ok = isInRange(str[0:2], 0, 23); !ok { - return false - } - if m, ok = isInRange(str[3:5], 0, 59); !ok { - return false - } - if s, ok = isInRange(str[6:8], 0, 60); !ok { - return false - } - str = str[8:] - - // parse secfrac if present - if str[0] == '.' { - // dot following more than one digit - str = str[1:] - var numDigits int - for str != "" { - if str[0] < '0' || str[0] > '9' { - break - } - numDigits++ - str = str[1:] - } - if numDigits == 0 { - return false - } - } - - if len(str) == 0 { - return false - } - - if str[0] == 'z' || str[0] == 'Z' { - if len(str) != 1 { - return false - } - } else { - // time-numoffset - // +hh:mm - // 012345 - if len(str) != 6 || str[3] != ':' { - return false - } - - var sign int - if str[0] == '+' { - sign = -1 - } else if str[0] == '-' { - sign = +1 - } else { - return false - } - - var zh, zm int - if zh, ok = isInRange(str[1:3], 0, 23); !ok { - return false - } - if zm, ok = isInRange(str[4:6], 0, 59); !ok { - return false - } - - // apply timezone offset - hm := (h*60 + m) + sign*(zh*60+zm) - if hm < 0 { - hm += 24 * 60 - } - h, m = hm/60, hm%60 - } - - // check leapsecond - if s == 60 { // leap second - if h != 23 || m != 59 { - return false - } - } - - return true -} - -// isDuration tells whether given string is a valid duration format -// from the ISO 8601 ABNF as given in Appendix A of RFC 3339. -// -// see https://datatracker.ietf.org/doc/html/rfc3339#appendix-A, for details -func isDuration(v interface{}) bool { - s, ok := v.(string) - if !ok { - return true - } - if len(s) == 0 || s[0] != 'P' { - return false - } - s = s[1:] - parseUnits := func() (units string, ok bool) { - for len(s) > 0 && s[0] != 'T' { - digits := false - for { - if len(s) == 0 { - break - } - if s[0] < '0' || s[0] > '9' { - break - } - digits = true - s = s[1:] - } - if !digits || len(s) == 0 { - return units, false - } - units += s[:1] - s = s[1:] - } - return units, true - } - units, ok := parseUnits() - if !ok { - return false - } - if units == "W" { - return len(s) == 0 // P_W - } - if len(units) > 0 { - if strings.Index("YMD", units) == -1 { - return false - } - if len(s) == 0 { - return true // "P" dur-date - } - } - if len(s) == 0 || s[0] != 'T' { - return false - } - s = s[1:] - units, ok = parseUnits() - return ok && len(s) == 0 && len(units) > 0 && strings.Index("HMS", units) != -1 -} - -// isPeriod tells whether given string is a valid period format -// from the ISO 8601 ABNF as given in Appendix A of RFC 3339. -// -// see https://datatracker.ietf.org/doc/html/rfc3339#appendix-A, for details -func isPeriod(v interface{}) bool { - s, ok := v.(string) - if !ok { - return true - } - slash := strings.IndexByte(s, '/') - if slash == -1 { - return false - } - start, end := s[:slash], s[slash+1:] - if isDateTime(start) { - return isDateTime(end) || isDuration(end) - } - return isDuration(start) && isDateTime(end) -} - -// isHostname tells whether given string is a valid representation -// for an Internet host name, as defined by RFC 1034 section 3.1 and -// RFC 1123 section 2.1. -// -// See https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names, for details. -func isHostname(v interface{}) bool { - s, ok := v.(string) - if !ok { - return true - } - // entire hostname (including the delimiting dots but not a trailing dot) has a maximum of 253 ASCII characters - s = strings.TrimSuffix(s, ".") - if len(s) > 253 { - return false - } - - // Hostnames are composed of series of labels concatenated with dots, as are all domain names - for _, label := range strings.Split(s, ".") { - // Each label must be from 1 to 63 characters long - if labelLen := len(label); labelLen < 1 || labelLen > 63 { - return false - } - - // labels must not start with a hyphen - // RFC 1123 section 2.1: restriction on the first character - // is relaxed to allow either a letter or a digit - if first := s[0]; first == '-' { - return false - } - - // must not end with a hyphen - if label[len(label)-1] == '-' { - return false - } - - // labels may contain only the ASCII letters 'a' through 'z' (in a case-insensitive manner), - // the digits '0' through '9', and the hyphen ('-') - for _, c := range label { - if valid := (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '-'); !valid { - return false - } - } - } - - return true -} - -// isEmail tells whether given string is a valid Internet email address -// as defined by RFC 5322, section 3.4.1. -// -// See https://en.wikipedia.org/wiki/Email_address, for details. -func isEmail(v interface{}) bool { - s, ok := v.(string) - if !ok { - return true - } - // entire email address to be no more than 254 characters long - if len(s) > 254 { - return false - } - - // email address is generally recognized as having two parts joined with an at-sign - at := strings.LastIndexByte(s, '@') - if at == -1 { - return false - } - local := s[0:at] - domain := s[at+1:] - - // local part may be up to 64 characters long - if len(local) > 64 { - return false - } - - // domain if enclosed in brackets, must match an IP address - if len(domain) >= 2 && domain[0] == '[' && domain[len(domain)-1] == ']' { - ip := domain[1 : len(domain)-1] - if strings.HasPrefix(ip, "IPv6:") { - return isIPV6(strings.TrimPrefix(ip, "IPv6:")) - } - return isIPV4(ip) - } - - // domain must match the requirements for a hostname - if !isHostname(domain) { - return false - } - - _, err := mail.ParseAddress(s) - return err == nil -} - -// isIPV4 tells whether given string is a valid representation of an IPv4 address -// according to the "dotted-quad" ABNF syntax as defined in RFC 2673, section 3.2. -func isIPV4(v interface{}) bool { - s, ok := v.(string) - if !ok { - return true - } - groups := strings.Split(s, ".") - if len(groups) != 4 { - return false - } - for _, group := range groups { - n, err := strconv.Atoi(group) - if err != nil { - return false - } - if n < 0 || n > 255 { - return false - } - if n != 0 && group[0] == '0' { - return false // leading zeroes should be rejected, as they are treated as octals - } - } - return true -} - -// isIPV6 tells whether given string is a valid representation of an IPv6 address -// as defined in RFC 2373, section 2.2. -func isIPV6(v interface{}) bool { - s, ok := v.(string) - if !ok { - return true - } - if !strings.Contains(s, ":") { - return false - } - return net.ParseIP(s) != nil -} - -// isURI tells whether given string is valid URI, according to RFC 3986. -func isURI(v interface{}) bool { - s, ok := v.(string) - if !ok { - return true - } - u, err := urlParse(s) - return err == nil && u.IsAbs() -} - -func urlParse(s string) (*url.URL, error) { - u, err := url.Parse(s) - if err != nil { - return nil, err - } - - // if hostname is ipv6, validate it - hostname := u.Hostname() - if strings.IndexByte(hostname, ':') != -1 { - if strings.IndexByte(u.Host, '[') == -1 || strings.IndexByte(u.Host, ']') == -1 { - return nil, errors.New("ipv6 address is not enclosed in brackets") - } - if !isIPV6(hostname) { - return nil, errors.New("invalid ipv6 address") - } - } - return u, nil -} - -// isURIReference tells whether given string is a valid URI Reference -// (either a URI or a relative-reference), according to RFC 3986. -func isURIReference(v interface{}) bool { - s, ok := v.(string) - if !ok { - return true - } - _, err := urlParse(s) - return err == nil && !strings.Contains(s, `\`) -} - -// isURITemplate tells whether given string is a valid URI Template -// according to RFC6570. -// -// Current implementation does minimal validation. -func isURITemplate(v interface{}) bool { - s, ok := v.(string) - if !ok { - return true - } - u, err := urlParse(s) - if err != nil { - return false - } - for _, item := range strings.Split(u.RawPath, "/") { - depth := 0 - for _, ch := range item { - switch ch { - case '{': - depth++ - if depth != 1 { - return false - } - case '}': - depth-- - if depth != 0 { - return false - } - } - } - if depth != 0 { - return false - } - } - return true -} - -// isRegex tells whether given string is a valid regular expression, -// according to the ECMA 262 regular expression dialect. -// -// The implementation uses go-lang regexp package. -func isRegex(v interface{}) bool { - s, ok := v.(string) - if !ok { - return true - } - _, err := regexp.Compile(s) - return err == nil -} - -// isJSONPointer tells whether given string is a valid JSON Pointer. -// -// Note: It returns false for JSON Pointer URI fragments. -func isJSONPointer(v interface{}) bool { - s, ok := v.(string) - if !ok { - return true - } - if s != "" && !strings.HasPrefix(s, "/") { - return false - } - for _, item := range strings.Split(s, "/") { - for i := 0; i < len(item); i++ { - if item[i] == '~' { - if i == len(item)-1 { - return false - } - switch item[i+1] { - case '0', '1': - // valid - default: - return false - } - } - } - } - return true -} - -// isRelativeJSONPointer tells whether given string is a valid Relative JSON Pointer. -// -// see https://tools.ietf.org/html/draft-handrews-relative-json-pointer-01#section-3 -func isRelativeJSONPointer(v interface{}) bool { - s, ok := v.(string) - if !ok { - return true - } - if s == "" { - return false - } - if s[0] == '0' { - s = s[1:] - } else if s[0] >= '0' && s[0] <= '9' { - for s != "" && s[0] >= '0' && s[0] <= '9' { - s = s[1:] - } - } else { - return false - } - return s == "#" || isJSONPointer(s) -} - -// isUUID tells whether given string is a valid uuid format -// as specified in RFC4122. -// -// see https://datatracker.ietf.org/doc/html/rfc4122#page-4, for details -func isUUID(v interface{}) bool { - s, ok := v.(string) - if !ok { - return true - } - parseHex := func(n int) bool { - for n > 0 { - if len(s) == 0 { - return false - } - hex := (s[0] >= '0' && s[0] <= '9') || (s[0] >= 'a' && s[0] <= 'f') || (s[0] >= 'A' && s[0] <= 'F') - if !hex { - return false - } - s = s[1:] - n-- - } - return true - } - groups := []int{8, 4, 4, 4, 12} - for i, numDigits := range groups { - if !parseHex(numDigits) { - return false - } - if i == len(groups)-1 { - break - } - if len(s) == 0 || s[0] != '-' { - return false - } - s = s[1:] - } - return len(s) == 0 -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v5/httploader/httploader.go b/vendor/github.com/santhosh-tekuri/jsonschema/v5/httploader/httploader.go deleted file mode 100644 index 4198cfe37..000000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/v5/httploader/httploader.go +++ /dev/null @@ -1,38 +0,0 @@ -// Package httploader implements loader.Loader for http/https url. -// -// The package is typically only imported for the side effect of -// registering its Loaders. -// -// To use httploader, link this package into your program: -// -// import _ "github.com/santhosh-tekuri/jsonschema/v5/httploader" -package httploader - -import ( - "fmt" - "io" - "net/http" - - "github.com/santhosh-tekuri/jsonschema/v5" -) - -// Client is the default HTTP Client used to Get the resource. -var Client = http.DefaultClient - -// Load loads resource from given http(s) url. -func Load(url string) (io.ReadCloser, error) { - resp, err := Client.Get(url) - if err != nil { - return nil, err - } - if resp.StatusCode != http.StatusOK { - _ = resp.Body.Close() - return nil, fmt.Errorf("%s returned status code %d", url, resp.StatusCode) - } - return resp.Body, nil -} - -func init() { - jsonschema.Loaders["http"] = Load - jsonschema.Loaders["https"] = Load -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v5/loader.go b/vendor/github.com/santhosh-tekuri/jsonschema/v5/loader.go deleted file mode 100644 index c94195c33..000000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/v5/loader.go +++ /dev/null @@ -1,60 +0,0 @@ -package jsonschema - -import ( - "fmt" - "io" - "net/url" - "os" - "path/filepath" - "runtime" - "strings" -) - -func loadFileURL(s string) (io.ReadCloser, error) { - u, err := url.Parse(s) - if err != nil { - return nil, err - } - f := u.Path - if runtime.GOOS == "windows" { - f = strings.TrimPrefix(f, "/") - f = filepath.FromSlash(f) - } - return os.Open(f) -} - -// Loaders is a registry of functions, which know how to load -// absolute url of specific schema. -// -// New loaders can be registered by adding to this map. Key is schema, -// value is function that knows how to load url of that schema -var Loaders = map[string]func(url string) (io.ReadCloser, error){ - "file": loadFileURL, -} - -// LoaderNotFoundError is the error type returned by Load function. -// It tells that no Loader is registered for that URL Scheme. -type LoaderNotFoundError string - -func (e LoaderNotFoundError) Error() string { - return fmt.Sprintf("jsonschema: no Loader found for %s", string(e)) -} - -// LoadURL loads document at given absolute URL. The default implementation -// uses Loaders registry to lookup by schema and uses that loader. -// -// Users can change this variable, if they would like to take complete -// responsibility of loading given URL. Used by Compiler if its LoadURL -// field is nil. -var LoadURL = func(s string) (io.ReadCloser, error) { - u, err := url.Parse(s) - if err != nil { - return nil, err - } - loader, ok := Loaders[u.Scheme] - if !ok { - return nil, LoaderNotFoundError(s) - - } - return loader(s) -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v5/output.go b/vendor/github.com/santhosh-tekuri/jsonschema/v5/output.go deleted file mode 100644 index d65ae2a92..000000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/v5/output.go +++ /dev/null @@ -1,77 +0,0 @@ -package jsonschema - -// Flag is output format with simple boolean property valid. -type Flag struct { - Valid bool `json:"valid"` -} - -// FlagOutput returns output in flag format -func (ve *ValidationError) FlagOutput() Flag { - return Flag{} -} - -// Basic --- - -// Basic is output format with flat list of output units. -type Basic struct { - Valid bool `json:"valid"` - Errors []BasicError `json:"errors"` -} - -// BasicError is output unit in basic format. -type BasicError struct { - KeywordLocation string `json:"keywordLocation"` - AbsoluteKeywordLocation string `json:"absoluteKeywordLocation"` - InstanceLocation string `json:"instanceLocation"` - Error string `json:"error"` -} - -// BasicOutput returns output in basic format -func (ve *ValidationError) BasicOutput() Basic { - var errors []BasicError - var flatten func(*ValidationError) - flatten = func(ve *ValidationError) { - errors = append(errors, BasicError{ - KeywordLocation: ve.KeywordLocation, - AbsoluteKeywordLocation: ve.AbsoluteKeywordLocation, - InstanceLocation: ve.InstanceLocation, - Error: ve.Message, - }) - for _, cause := range ve.Causes { - flatten(cause) - } - } - flatten(ve) - return Basic{Errors: errors} -} - -// Detailed --- - -// Detailed is output format based on structure of schema. -type Detailed struct { - Valid bool `json:"valid"` - KeywordLocation string `json:"keywordLocation"` - AbsoluteKeywordLocation string `json:"absoluteKeywordLocation"` - InstanceLocation string `json:"instanceLocation"` - Error string `json:"error,omitempty"` - Errors []Detailed `json:"errors,omitempty"` -} - -// DetailedOutput returns output in detailed format -func (ve *ValidationError) DetailedOutput() Detailed { - var errors []Detailed - for _, cause := range ve.Causes { - errors = append(errors, cause.DetailedOutput()) - } - var message = ve.Message - if len(ve.Causes) > 0 { - message = "" - } - return Detailed{ - KeywordLocation: ve.KeywordLocation, - AbsoluteKeywordLocation: ve.AbsoluteKeywordLocation, - InstanceLocation: ve.InstanceLocation, - Error: message, - Errors: errors, - } -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v5/resource.go b/vendor/github.com/santhosh-tekuri/jsonschema/v5/resource.go deleted file mode 100644 index 18349daac..000000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/v5/resource.go +++ /dev/null @@ -1,280 +0,0 @@ -package jsonschema - -import ( - "encoding/json" - "fmt" - "io" - "net/url" - "path/filepath" - "runtime" - "strconv" - "strings" -) - -type resource struct { - url string // base url of resource. can be empty - floc string // fragment with json-pointer from root resource - doc interface{} - draft *Draft - subresources map[string]*resource // key is floc. only applicable for root resource - schema *Schema -} - -func (r *resource) String() string { - return r.url + r.floc -} - -func newResource(url string, r io.Reader) (*resource, error) { - if strings.IndexByte(url, '#') != -1 { - panic(fmt.Sprintf("BUG: newResource(%q)", url)) - } - doc, err := unmarshal(r) - if err != nil { - return nil, fmt.Errorf("jsonschema: invalid json %s: %v", url, err) - } - url, err = toAbs(url) - if err != nil { - return nil, err - } - return &resource{ - url: url, - floc: "#", - doc: doc, - }, nil -} - -// fillSubschemas fills subschemas in res into r.subresources -func (r *resource) fillSubschemas(c *Compiler, res *resource) error { - if err := c.validateSchema(r, res.doc, res.floc[1:]); err != nil { - return err - } - - if r.subresources == nil { - r.subresources = make(map[string]*resource) - } - if err := r.draft.listSubschemas(res, r.baseURL(res.floc), r.subresources); err != nil { - return err - } - - // ensure subresource.url uniqueness - url2floc := make(map[string]string) - for _, sr := range r.subresources { - if sr.url != "" { - if floc, ok := url2floc[sr.url]; ok { - return fmt.Errorf("jsonschema: %q and %q in %s have same canonical-uri", floc[1:], sr.floc[1:], r.url) - } - url2floc[sr.url] = sr.floc - } - } - - return nil -} - -// listResources lists all subresources in res -func (r *resource) listResources(res *resource) []*resource { - var result []*resource - prefix := res.floc + "/" - for _, sr := range r.subresources { - if strings.HasPrefix(sr.floc, prefix) { - result = append(result, sr) - } - } - return result -} - -func (r *resource) findResource(url string) *resource { - if r.url == url { - return r - } - for _, res := range r.subresources { - if res.url == url { - return res - } - } - return nil -} - -// resolve fragment f with sr as base -func (r *resource) resolveFragment(c *Compiler, sr *resource, f string) (*resource, error) { - if f == "#" || f == "#/" { - return sr, nil - } - - // resolve by anchor - if !strings.HasPrefix(f, "#/") { - // check in given resource - for _, anchor := range r.draft.anchors(sr.doc) { - if anchor == f[1:] { - return sr, nil - } - } - - // check in subresources that has same base url - prefix := sr.floc + "/" - for _, res := range r.subresources { - if strings.HasPrefix(res.floc, prefix) && r.baseURL(res.floc) == sr.url { - for _, anchor := range r.draft.anchors(res.doc) { - if anchor == f[1:] { - return res, nil - } - } - } - } - return nil, nil - } - - // resolve by ptr - floc := sr.floc + f[1:] - if res, ok := r.subresources[floc]; ok { - return res, nil - } - - // non-standrad location - doc := r.doc - for _, item := range strings.Split(floc[2:], "/") { - item = strings.Replace(item, "~1", "/", -1) - item = strings.Replace(item, "~0", "~", -1) - item, err := url.PathUnescape(item) - if err != nil { - return nil, err - } - switch d := doc.(type) { - case map[string]interface{}: - if _, ok := d[item]; !ok { - return nil, nil - } - doc = d[item] - case []interface{}: - index, err := strconv.Atoi(item) - if err != nil { - return nil, err - } - if index < 0 || index >= len(d) { - return nil, nil - } - doc = d[index] - default: - return nil, nil - } - } - - id, err := r.draft.resolveID(r.baseURL(floc), doc) - if err != nil { - return nil, err - } - res := &resource{url: id, floc: floc, doc: doc} - r.subresources[floc] = res - if err := r.fillSubschemas(c, res); err != nil { - return nil, err - } - return res, nil -} - -func (r *resource) baseURL(floc string) string { - for { - if sr, ok := r.subresources[floc]; ok { - if sr.url != "" { - return sr.url - } - } - slash := strings.LastIndexByte(floc, '/') - if slash == -1 { - break - } - floc = floc[:slash] - } - return r.url -} - -// url helpers --- - -func toAbs(s string) (string, error) { - // if windows absolute file path, convert to file url - // because: net/url parses driver name as scheme - if runtime.GOOS == "windows" && len(s) >= 3 && s[1:3] == `:\` { - s = "file:///" + filepath.ToSlash(s) - } - - u, err := url.Parse(s) - if err != nil { - return "", err - } - if u.IsAbs() { - return s, nil - } - - // s is filepath - if s, err = filepath.Abs(s); err != nil { - return "", err - } - if runtime.GOOS == "windows" { - s = "file:///" + filepath.ToSlash(s) - } else { - s = "file://" + s - } - u, err = url.Parse(s) // to fix spaces in filepath - return u.String(), err -} - -func resolveURL(base, ref string) (string, error) { - if ref == "" { - return base, nil - } - if strings.HasPrefix(ref, "urn:") { - return ref, nil - } - - refURL, err := url.Parse(ref) - if err != nil { - return "", err - } - if refURL.IsAbs() { - return ref, nil - } - - if strings.HasPrefix(base, "urn:") { - base, _ = split(base) - return base + ref, nil - } - - baseURL, err := url.Parse(base) - if err != nil { - return "", err - } - return baseURL.ResolveReference(refURL).String(), nil -} - -func split(uri string) (string, string) { - hash := strings.IndexByte(uri, '#') - if hash == -1 { - return uri, "#" - } - f := uri[hash:] - if f == "#/" { - f = "#" - } - return uri[0:hash], f -} - -func (s *Schema) url() string { - u, _ := split(s.Location) - return u -} - -func (s *Schema) loc() string { - _, f := split(s.Location) - return f[1:] -} - -func unmarshal(r io.Reader) (interface{}, error) { - decoder := json.NewDecoder(r) - decoder.UseNumber() - var doc interface{} - if err := decoder.Decode(&doc); err != nil { - return nil, err - } - if t, _ := decoder.Token(); t != nil { - return nil, fmt.Errorf("invalid character %v after top-level value", t) - } - return doc, nil -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/v5/schema.go b/vendor/github.com/santhosh-tekuri/jsonschema/v5/schema.go deleted file mode 100644 index 688f0a6fe..000000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/v5/schema.go +++ /dev/null @@ -1,900 +0,0 @@ -package jsonschema - -import ( - "bytes" - "encoding/json" - "fmt" - "hash/maphash" - "math/big" - "net/url" - "regexp" - "sort" - "strconv" - "strings" - "unicode/utf8" -) - -// A Schema represents compiled version of json-schema. -type Schema struct { - Location string // absolute location - - Draft *Draft // draft used by schema. - meta *Schema - vocab []string - dynamicAnchors []*Schema - - // type agnostic validations - Format string - format func(interface{}) bool - Always *bool // always pass/fail. used when booleans are used as schemas in draft-07. - Ref *Schema - RecursiveAnchor bool - RecursiveRef *Schema - DynamicAnchor string - DynamicRef *Schema - dynamicRefAnchor string - Types []string // allowed types. - Constant []interface{} // first element in slice is constant value. note: slice is used to capture nil constant. - Enum []interface{} // allowed values. - enumError string // error message for enum fail. captured here to avoid constructing error message every time. - Not *Schema - AllOf []*Schema - AnyOf []*Schema - OneOf []*Schema - If *Schema - Then *Schema // nil, when If is nil. - Else *Schema // nil, when If is nil. - - // object validations - MinProperties int // -1 if not specified. - MaxProperties int // -1 if not specified. - Required []string // list of required properties. - Properties map[string]*Schema - PropertyNames *Schema - RegexProperties bool // property names must be valid regex. used only in draft4 as workaround in metaschema. - PatternProperties map[*regexp.Regexp]*Schema - AdditionalProperties interface{} // nil or bool or *Schema. - Dependencies map[string]interface{} // map value is *Schema or []string. - DependentRequired map[string][]string - DependentSchemas map[string]*Schema - UnevaluatedProperties *Schema - - // array validations - MinItems int // -1 if not specified. - MaxItems int // -1 if not specified. - UniqueItems bool - Items interface{} // nil or *Schema or []*Schema - AdditionalItems interface{} // nil or bool or *Schema. - PrefixItems []*Schema - Items2020 *Schema // items keyword reintroduced in draft 2020-12 - Contains *Schema - ContainsEval bool // whether any item in an array that passes validation of the contains schema is considered "evaluated" - MinContains int // 1 if not specified - MaxContains int // -1 if not specified - UnevaluatedItems *Schema - - // string validations - MinLength int // -1 if not specified. - MaxLength int // -1 if not specified. - Pattern *regexp.Regexp - ContentEncoding string - decoder func(string) ([]byte, error) - ContentMediaType string - mediaType func([]byte) error - ContentSchema *Schema - - // number validators - Minimum *big.Rat - ExclusiveMinimum *big.Rat - Maximum *big.Rat - ExclusiveMaximum *big.Rat - MultipleOf *big.Rat - - // annotations. captured only when Compiler.ExtractAnnotations is true. - Title string - Description string - Default interface{} - Comment string - ReadOnly bool - WriteOnly bool - Examples []interface{} - Deprecated bool - - // user defined extensions - Extensions map[string]ExtSchema -} - -func (s *Schema) String() string { - return s.Location -} - -func newSchema(url, floc string, draft *Draft, doc interface{}) *Schema { - // fill with default values - s := &Schema{ - Location: url + floc, - Draft: draft, - MinProperties: -1, - MaxProperties: -1, - MinItems: -1, - MaxItems: -1, - MinContains: 1, - MaxContains: -1, - MinLength: -1, - MaxLength: -1, - } - - if doc, ok := doc.(map[string]interface{}); ok { - if ra, ok := doc["$recursiveAnchor"]; ok { - if ra, ok := ra.(bool); ok { - s.RecursiveAnchor = ra - } - } - if da, ok := doc["$dynamicAnchor"]; ok { - if da, ok := da.(string); ok { - s.DynamicAnchor = da - } - } - } - return s -} - -func (s *Schema) hasVocab(name string) bool { - if s == nil { // during bootstrap - return true - } - if name == "core" { - return true - } - for _, url := range s.vocab { - if url == "https://json-schema.org/draft/2019-09/vocab/"+name { - return true - } - if url == "https://json-schema.org/draft/2020-12/vocab/"+name { - return true - } - } - return false -} - -// Validate validates given doc, against the json-schema s. -// -// the v must be the raw json value. for number precision -// unmarshal with json.UseNumber(). -// -// returns *ValidationError if v does not confirm with schema s. -// returns InfiniteLoopError if it detects loop during validation. -// returns InvalidJSONTypeError if it detects any non json value in v. -func (s *Schema) Validate(v interface{}) (err error) { - return s.validateValue(v, "") -} - -func (s *Schema) validateValue(v interface{}, vloc string) (err error) { - defer func() { - if r := recover(); r != nil { - switch r := r.(type) { - case InfiniteLoopError, InvalidJSONTypeError: - err = r.(error) - default: - panic(r) - } - } - }() - if _, err := s.validate(nil, 0, "", v, vloc); err != nil { - ve := ValidationError{ - KeywordLocation: "", - AbsoluteKeywordLocation: s.Location, - InstanceLocation: vloc, - Message: fmt.Sprintf("doesn't validate with %s", s.Location), - } - return ve.causes(err) - } - return nil -} - -// validate validates given value v with this schema. -func (s *Schema) validate(scope []schemaRef, vscope int, spath string, v interface{}, vloc string) (result validationResult, err error) { - validationError := func(keywordPath string, format string, a ...interface{}) *ValidationError { - return &ValidationError{ - KeywordLocation: keywordLocation(scope, keywordPath), - AbsoluteKeywordLocation: joinPtr(s.Location, keywordPath), - InstanceLocation: vloc, - Message: fmt.Sprintf(format, a...), - } - } - - sref := schemaRef{spath, s, false} - if err := checkLoop(scope[len(scope)-vscope:], sref); err != nil { - panic(err) - } - scope = append(scope, sref) - vscope++ - - // populate result - switch v := v.(type) { - case map[string]interface{}: - result.unevalProps = make(map[string]struct{}) - for pname := range v { - result.unevalProps[pname] = struct{}{} - } - case []interface{}: - result.unevalItems = make(map[int]struct{}) - for i := range v { - result.unevalItems[i] = struct{}{} - } - } - - validate := func(sch *Schema, schPath string, v interface{}, vpath string) error { - vloc := vloc - if vpath != "" { - vloc += "/" + vpath - } - _, err := sch.validate(scope, 0, schPath, v, vloc) - return err - } - - validateInplace := func(sch *Schema, schPath string) error { - vr, err := sch.validate(scope, vscope, schPath, v, vloc) - if err == nil { - // update result - for pname := range result.unevalProps { - if _, ok := vr.unevalProps[pname]; !ok { - delete(result.unevalProps, pname) - } - } - for i := range result.unevalItems { - if _, ok := vr.unevalItems[i]; !ok { - delete(result.unevalItems, i) - } - } - } - return err - } - - if s.Always != nil { - if !*s.Always { - return result, validationError("", "not allowed") - } - return result, nil - } - - if len(s.Types) > 0 { - vType := jsonType(v) - matched := false - for _, t := range s.Types { - if vType == t { - matched = true - break - } else if t == "integer" && vType == "number" { - num, _ := new(big.Rat).SetString(fmt.Sprint(v)) - if num.IsInt() { - matched = true - break - } - } - } - if !matched { - return result, validationError("type", "expected %s, but got %s", strings.Join(s.Types, " or "), vType) - } - } - - var errors []error - - if len(s.Constant) > 0 { - if !equals(v, s.Constant[0]) { - switch jsonType(s.Constant[0]) { - case "object", "array": - errors = append(errors, validationError("const", "const failed")) - default: - errors = append(errors, validationError("const", "value must be %#v", s.Constant[0])) - } - } - } - - if len(s.Enum) > 0 { - matched := false - for _, item := range s.Enum { - if equals(v, item) { - matched = true - break - } - } - if !matched { - errors = append(errors, validationError("enum", s.enumError)) - } - } - - if s.format != nil && !s.format(v) { - var val = v - if v, ok := v.(string); ok { - val = quote(v) - } - errors = append(errors, validationError("format", "%v is not valid %s", val, quote(s.Format))) - } - - switch v := v.(type) { - case map[string]interface{}: - if s.MinProperties != -1 && len(v) < s.MinProperties { - errors = append(errors, validationError("minProperties", "minimum %d properties allowed, but found %d properties", s.MinProperties, len(v))) - } - if s.MaxProperties != -1 && len(v) > s.MaxProperties { - errors = append(errors, validationError("maxProperties", "maximum %d properties allowed, but found %d properties", s.MaxProperties, len(v))) - } - if len(s.Required) > 0 { - var missing []string - for _, pname := range s.Required { - if _, ok := v[pname]; !ok { - missing = append(missing, quote(pname)) - } - } - if len(missing) > 0 { - errors = append(errors, validationError("required", "missing properties: %s", strings.Join(missing, ", "))) - } - } - - for pname, sch := range s.Properties { - if pvalue, ok := v[pname]; ok { - delete(result.unevalProps, pname) - if err := validate(sch, "properties/"+escape(pname), pvalue, escape(pname)); err != nil { - errors = append(errors, err) - } - } - } - - if s.PropertyNames != nil { - for pname := range v { - if err := validate(s.PropertyNames, "propertyNames", pname, escape(pname)); err != nil { - errors = append(errors, err) - } - } - } - - if s.RegexProperties { - for pname := range v { - if !isRegex(pname) { - errors = append(errors, validationError("", "patternProperty %s is not valid regex", quote(pname))) - } - } - } - for pattern, sch := range s.PatternProperties { - for pname, pvalue := range v { - if pattern.MatchString(pname) { - delete(result.unevalProps, pname) - if err := validate(sch, "patternProperties/"+escape(pattern.String()), pvalue, escape(pname)); err != nil { - errors = append(errors, err) - } - } - } - } - if s.AdditionalProperties != nil { - if allowed, ok := s.AdditionalProperties.(bool); ok { - if !allowed && len(result.unevalProps) > 0 { - errors = append(errors, validationError("additionalProperties", "additionalProperties %s not allowed", result.unevalPnames())) - } - } else { - schema := s.AdditionalProperties.(*Schema) - for pname := range result.unevalProps { - if pvalue, ok := v[pname]; ok { - if err := validate(schema, "additionalProperties", pvalue, escape(pname)); err != nil { - errors = append(errors, err) - } - } - } - } - result.unevalProps = nil - } - for dname, dvalue := range s.Dependencies { - if _, ok := v[dname]; ok { - switch dvalue := dvalue.(type) { - case *Schema: - if err := validateInplace(dvalue, "dependencies/"+escape(dname)); err != nil { - errors = append(errors, err) - } - case []string: - for i, pname := range dvalue { - if _, ok := v[pname]; !ok { - errors = append(errors, validationError("dependencies/"+escape(dname)+"/"+strconv.Itoa(i), "property %s is required, if %s property exists", quote(pname), quote(dname))) - } - } - } - } - } - for dname, dvalue := range s.DependentRequired { - if _, ok := v[dname]; ok { - for i, pname := range dvalue { - if _, ok := v[pname]; !ok { - errors = append(errors, validationError("dependentRequired/"+escape(dname)+"/"+strconv.Itoa(i), "property %s is required, if %s property exists", quote(pname), quote(dname))) - } - } - } - } - for dname, sch := range s.DependentSchemas { - if _, ok := v[dname]; ok { - if err := validateInplace(sch, "dependentSchemas/"+escape(dname)); err != nil { - errors = append(errors, err) - } - } - } - - case []interface{}: - if s.MinItems != -1 && len(v) < s.MinItems { - errors = append(errors, validationError("minItems", "minimum %d items required, but found %d items", s.MinItems, len(v))) - } - if s.MaxItems != -1 && len(v) > s.MaxItems { - errors = append(errors, validationError("maxItems", "maximum %d items required, but found %d items", s.MaxItems, len(v))) - } - if s.UniqueItems { - if len(v) <= 20 { - outer1: - for i := 1; i < len(v); i++ { - for j := 0; j < i; j++ { - if equals(v[i], v[j]) { - errors = append(errors, validationError("uniqueItems", "items at index %d and %d are equal", j, i)) - break outer1 - } - } - } - } else { - m := make(map[uint64][]int) - var h maphash.Hash - outer2: - for i, item := range v { - h.Reset() - hash(item, &h) - k := h.Sum64() - if err != nil { - panic(err) - } - arr, ok := m[k] - if ok { - for _, j := range arr { - if equals(v[j], item) { - errors = append(errors, validationError("uniqueItems", "items at index %d and %d are equal", j, i)) - break outer2 - } - } - } - arr = append(arr, i) - m[k] = arr - } - } - } - - // items + additionalItems - switch items := s.Items.(type) { - case *Schema: - for i, item := range v { - if err := validate(items, "items", item, strconv.Itoa(i)); err != nil { - errors = append(errors, err) - } - } - result.unevalItems = nil - case []*Schema: - for i, item := range v { - if i < len(items) { - delete(result.unevalItems, i) - if err := validate(items[i], "items/"+strconv.Itoa(i), item, strconv.Itoa(i)); err != nil { - errors = append(errors, err) - } - } else if sch, ok := s.AdditionalItems.(*Schema); ok { - delete(result.unevalItems, i) - if err := validate(sch, "additionalItems", item, strconv.Itoa(i)); err != nil { - errors = append(errors, err) - } - } else { - break - } - } - if additionalItems, ok := s.AdditionalItems.(bool); ok { - if additionalItems { - result.unevalItems = nil - } else if len(v) > len(items) { - errors = append(errors, validationError("additionalItems", "only %d items are allowed, but found %d items", len(items), len(v))) - } - } - } - - // prefixItems + items - for i, item := range v { - if i < len(s.PrefixItems) { - delete(result.unevalItems, i) - if err := validate(s.PrefixItems[i], "prefixItems/"+strconv.Itoa(i), item, strconv.Itoa(i)); err != nil { - errors = append(errors, err) - } - } else if s.Items2020 != nil { - delete(result.unevalItems, i) - if err := validate(s.Items2020, "items", item, strconv.Itoa(i)); err != nil { - errors = append(errors, err) - } - } else { - break - } - } - - // contains + minContains + maxContains - if s.Contains != nil && (s.MinContains != -1 || s.MaxContains != -1) { - matched := 0 - var causes []error - for i, item := range v { - if err := validate(s.Contains, "contains", item, strconv.Itoa(i)); err != nil { - causes = append(causes, err) - } else { - matched++ - if s.ContainsEval { - delete(result.unevalItems, i) - } - } - } - if s.MinContains != -1 && matched < s.MinContains { - errors = append(errors, validationError("minContains", "valid must be >= %d, but got %d", s.MinContains, matched).add(causes...)) - } - if s.MaxContains != -1 && matched > s.MaxContains { - errors = append(errors, validationError("maxContains", "valid must be <= %d, but got %d", s.MaxContains, matched)) - } - } - - case string: - // minLength + maxLength - if s.MinLength != -1 || s.MaxLength != -1 { - length := utf8.RuneCount([]byte(v)) - if s.MinLength != -1 && length < s.MinLength { - errors = append(errors, validationError("minLength", "length must be >= %d, but got %d", s.MinLength, length)) - } - if s.MaxLength != -1 && length > s.MaxLength { - errors = append(errors, validationError("maxLength", "length must be <= %d, but got %d", s.MaxLength, length)) - } - } - - if s.Pattern != nil && !s.Pattern.MatchString(v) { - errors = append(errors, validationError("pattern", "does not match pattern %s", quote(s.Pattern.String()))) - } - - // contentEncoding + contentMediaType - if s.decoder != nil || s.mediaType != nil { - decoded := s.ContentEncoding == "" - var content []byte - if s.decoder != nil { - b, err := s.decoder(v) - if err != nil { - errors = append(errors, validationError("contentEncoding", "value is not %s encoded", s.ContentEncoding)) - } else { - content, decoded = b, true - } - } - if decoded && s.mediaType != nil { - if s.decoder == nil { - content = []byte(v) - } - if err := s.mediaType(content); err != nil { - errors = append(errors, validationError("contentMediaType", "value is not of mediatype %s", quote(s.ContentMediaType))) - } - } - if decoded && s.ContentSchema != nil { - contentJSON, err := unmarshal(bytes.NewReader(content)) - if err != nil { - errors = append(errors, validationError("contentSchema", "value is not valid json")) - } else { - err := validate(s.ContentSchema, "contentSchema", contentJSON, "") - if err != nil { - errors = append(errors, err) - } - } - } - } - - case json.Number, float32, float64, int, int8, int32, int64, uint, uint8, uint32, uint64: - // lazy convert to *big.Rat to avoid allocation - var numVal *big.Rat - num := func() *big.Rat { - if numVal == nil { - numVal, _ = new(big.Rat).SetString(fmt.Sprint(v)) - } - return numVal - } - f64 := func(r *big.Rat) float64 { - f, _ := r.Float64() - return f - } - if s.Minimum != nil && num().Cmp(s.Minimum) < 0 { - errors = append(errors, validationError("minimum", "must be >= %v but found %v", f64(s.Minimum), v)) - } - if s.ExclusiveMinimum != nil && num().Cmp(s.ExclusiveMinimum) <= 0 { - errors = append(errors, validationError("exclusiveMinimum", "must be > %v but found %v", f64(s.ExclusiveMinimum), v)) - } - if s.Maximum != nil && num().Cmp(s.Maximum) > 0 { - errors = append(errors, validationError("maximum", "must be <= %v but found %v", f64(s.Maximum), v)) - } - if s.ExclusiveMaximum != nil && num().Cmp(s.ExclusiveMaximum) >= 0 { - errors = append(errors, validationError("exclusiveMaximum", "must be < %v but found %v", f64(s.ExclusiveMaximum), v)) - } - if s.MultipleOf != nil { - if q := new(big.Rat).Quo(num(), s.MultipleOf); !q.IsInt() { - errors = append(errors, validationError("multipleOf", "%v not multipleOf %v", v, f64(s.MultipleOf))) - } - } - } - - // $ref + $recursiveRef + $dynamicRef - validateRef := func(sch *Schema, refPath string) error { - if sch != nil { - if err := validateInplace(sch, refPath); err != nil { - var url = sch.Location - if s.url() == sch.url() { - url = sch.loc() - } - return validationError(refPath, "doesn't validate with %s", quote(url)).causes(err) - } - } - return nil - } - if err := validateRef(s.Ref, "$ref"); err != nil { - errors = append(errors, err) - } - if s.RecursiveRef != nil { - sch := s.RecursiveRef - if sch.RecursiveAnchor { - // recursiveRef based on scope - for _, e := range scope { - if e.schema.RecursiveAnchor { - sch = e.schema - break - } - } - } - if err := validateRef(sch, "$recursiveRef"); err != nil { - errors = append(errors, err) - } - } - if s.DynamicRef != nil { - sch := s.DynamicRef - if s.dynamicRefAnchor != "" && sch.DynamicAnchor == s.dynamicRefAnchor { - // dynamicRef based on scope - for i := len(scope) - 1; i >= 0; i-- { - sr := scope[i] - if sr.discard { - break - } - for _, da := range sr.schema.dynamicAnchors { - if da.DynamicAnchor == s.DynamicRef.DynamicAnchor && da != s.DynamicRef { - sch = da - break - } - } - } - } - if err := validateRef(sch, "$dynamicRef"); err != nil { - errors = append(errors, err) - } - } - - if s.Not != nil && validateInplace(s.Not, "not") == nil { - errors = append(errors, validationError("not", "not failed")) - } - - for i, sch := range s.AllOf { - schPath := "allOf/" + strconv.Itoa(i) - if err := validateInplace(sch, schPath); err != nil { - errors = append(errors, validationError(schPath, "allOf failed").add(err)) - } - } - - if len(s.AnyOf) > 0 { - matched := false - var causes []error - for i, sch := range s.AnyOf { - if err := validateInplace(sch, "anyOf/"+strconv.Itoa(i)); err == nil { - matched = true - } else { - causes = append(causes, err) - } - } - if !matched { - errors = append(errors, validationError("anyOf", "anyOf failed").add(causes...)) - } - } - - if len(s.OneOf) > 0 { - matched := -1 - var causes []error - for i, sch := range s.OneOf { - if err := validateInplace(sch, "oneOf/"+strconv.Itoa(i)); err == nil { - if matched == -1 { - matched = i - } else { - errors = append(errors, validationError("oneOf", "valid against schemas at indexes %d and %d", matched, i)) - break - } - } else { - causes = append(causes, err) - } - } - if matched == -1 { - errors = append(errors, validationError("oneOf", "oneOf failed").add(causes...)) - } - } - - // if + then + else - if s.If != nil { - err := validateInplace(s.If, "if") - // "if" leaves dynamic scope - scope[len(scope)-1].discard = true - if err == nil { - if s.Then != nil { - if err := validateInplace(s.Then, "then"); err != nil { - errors = append(errors, validationError("then", "if-then failed").add(err)) - } - } - } else { - if s.Else != nil { - if err := validateInplace(s.Else, "else"); err != nil { - errors = append(errors, validationError("else", "if-else failed").add(err)) - } - } - } - // restore dynamic scope - scope[len(scope)-1].discard = false - } - - for _, ext := range s.Extensions { - if err := ext.Validate(ValidationContext{result, validate, validateInplace, validationError}, v); err != nil { - errors = append(errors, err) - } - } - - // unevaluatedProperties + unevaluatedItems - switch v := v.(type) { - case map[string]interface{}: - if s.UnevaluatedProperties != nil { - for pname := range result.unevalProps { - if pvalue, ok := v[pname]; ok { - if err := validate(s.UnevaluatedProperties, "unevaluatedProperties", pvalue, escape(pname)); err != nil { - errors = append(errors, err) - } - } - } - result.unevalProps = nil - } - case []interface{}: - if s.UnevaluatedItems != nil { - for i := range result.unevalItems { - if err := validate(s.UnevaluatedItems, "unevaluatedItems", v[i], strconv.Itoa(i)); err != nil { - errors = append(errors, err) - } - } - result.unevalItems = nil - } - } - - switch len(errors) { - case 0: - return result, nil - case 1: - return result, errors[0] - default: - return result, validationError("", "").add(errors...) // empty message, used just for wrapping - } -} - -type validationResult struct { - unevalProps map[string]struct{} - unevalItems map[int]struct{} -} - -func (vr validationResult) unevalPnames() string { - pnames := make([]string, 0, len(vr.unevalProps)) - for pname := range vr.unevalProps { - pnames = append(pnames, quote(pname)) - } - return strings.Join(pnames, ", ") -} - -// jsonType returns the json type of given value v. -// -// It panics if the given value is not valid json value -func jsonType(v interface{}) string { - switch v.(type) { - case nil: - return "null" - case bool: - return "boolean" - case json.Number, float32, float64, int, int8, int32, int64, uint, uint8, uint32, uint64: - return "number" - case string: - return "string" - case []interface{}: - return "array" - case map[string]interface{}: - return "object" - } - panic(InvalidJSONTypeError(fmt.Sprintf("%T", v))) -} - -// equals tells if given two json values are equal or not. -func equals(v1, v2 interface{}) bool { - v1Type := jsonType(v1) - if v1Type != jsonType(v2) { - return false - } - switch v1Type { - case "array": - arr1, arr2 := v1.([]interface{}), v2.([]interface{}) - if len(arr1) != len(arr2) { - return false - } - for i := range arr1 { - if !equals(arr1[i], arr2[i]) { - return false - } - } - return true - case "object": - obj1, obj2 := v1.(map[string]interface{}), v2.(map[string]interface{}) - if len(obj1) != len(obj2) { - return false - } - for k, v1 := range obj1 { - if v2, ok := obj2[k]; ok { - if !equals(v1, v2) { - return false - } - } else { - return false - } - } - return true - case "number": - num1, _ := new(big.Rat).SetString(fmt.Sprint(v1)) - num2, _ := new(big.Rat).SetString(fmt.Sprint(v2)) - return num1.Cmp(num2) == 0 - default: - return v1 == v2 - } -} - -func hash(v interface{}, h *maphash.Hash) { - switch v := v.(type) { - case nil: - h.WriteByte(0) - case bool: - h.WriteByte(1) - if v { - h.WriteByte(1) - } else { - h.WriteByte(0) - } - case json.Number, float32, float64, int, int8, int32, int64, uint, uint8, uint32, uint64: - h.WriteByte(2) - num, _ := new(big.Rat).SetString(fmt.Sprint(v)) - h.Write(num.Num().Bytes()) - h.Write(num.Denom().Bytes()) - case string: - h.WriteByte(3) - h.WriteString(v) - case []interface{}: - h.WriteByte(4) - for _, item := range v { - hash(item, h) - } - case map[string]interface{}: - h.WriteByte(5) - props := make([]string, 0, len(v)) - for prop := range v { - props = append(props, prop) - } - sort.Slice(props, func(i, j int) bool { - return props[i] < props[j] - }) - for _, prop := range props { - hash(prop, h) - hash(v[prop], h) - } - default: - panic(InvalidJSONTypeError(fmt.Sprintf("%T", v))) - } -} - -// escape converts given token to valid json-pointer token -func escape(token string) string { - token = strings.ReplaceAll(token, "~", "~0") - token = strings.ReplaceAll(token, "/", "~1") - return url.PathEscape(token) -} |
