├── .circleci ├── config.yml └── cover.test.sh ├── .github └── CONTRIBUTING.md ├── .gitignore ├── CHANGELOG.md ├── DEVELOPERS.md ├── LICENSE ├── Makefile ├── README.md ├── code_of_conduct.md ├── codecov.yml ├── draft2019_09_keywords.go ├── go.mod ├── go.sum ├── keyword.go ├── keyword_test.go ├── keywords_array.go ├── keywords_boolean.go ├── keywords_conditional.go ├── keywords_core.go ├── keywords_numeric.go ├── keywords_object.go ├── keywords_optional.go ├── keywords_standard.go ├── keywords_string.go ├── schema.go ├── schema_loader.go ├── schema_loader_test.go ├── schema_registry.go ├── schema_test.go ├── testdata ├── coding │ ├── arrays.json │ ├── booleans.json │ ├── conditionals.json │ ├── false.json │ ├── numeric.json │ ├── objects.json │ ├── std.json │ ├── strings.json │ └── true.json ├── draft-07_schema.json ├── draft2019-09 │ ├── additionalItems.json │ ├── additionalProperties.json │ ├── additionalProperties_modified.json │ ├── allOf.json │ ├── anchor.json │ ├── anyOf.json │ ├── boolean_schema.json │ ├── const.json │ ├── contains.json │ ├── default.json │ ├── defs.json │ ├── dependentRequired.json │ ├── dependentSchemas.json │ ├── enum.json │ ├── exclusiveMaximum.json │ ├── exclusiveMinimum.json │ ├── format.json │ ├── if-then-else.json │ ├── items.json │ ├── maxItems.json │ ├── maxLength.json │ ├── maxProperties.json │ ├── maximum.json │ ├── minItems.json │ ├── minLength.json │ ├── minProperties.json │ ├── minimum.json │ ├── multipleOf.json │ ├── not.json │ ├── oneOf.json │ ├── optional │ │ ├── bignum.json │ │ ├── content.json │ │ ├── ecmascript-regex.json │ │ ├── format │ │ │ ├── date-time.json │ │ │ ├── date.json │ │ │ ├── email.json │ │ │ ├── hostname.json │ │ │ ├── idn-email.json │ │ │ ├── idn-hostname.json │ │ │ ├── ipv4.json │ │ │ ├── ipv6.json │ │ │ ├── iri-reference.json │ │ │ ├── iri.json │ │ │ ├── json-pointer.json │ │ │ ├── regex.json │ │ │ ├── relative-json-pointer.json │ │ │ ├── time.json │ │ │ ├── uri-reference.json │ │ │ ├── uri-template.json │ │ │ └── uri.json │ │ ├── refOfUnknownKeyword.json │ │ └── zeroTerminatedFloats.json │ ├── pattern.json │ ├── patternProperties.json │ ├── properties.json │ ├── propertyNames.json │ ├── ref.json │ ├── refRemote.json │ ├── required.json │ ├── type.json │ ├── unevaluatedItems.json │ ├── unevaluatedItems_modified.json │ ├── unevaluatedProperties.json │ ├── unevaluatedProperties_modified.json │ └── uniqueItems.json ├── draft2019-09_schema.json ├── draft3 │ ├── additionalItems.json │ ├── additionalProperties.json │ ├── default.json │ ├── dependencies.json │ ├── disallow.json │ ├── divisibleBy.json │ ├── enum.json │ ├── extends.json │ ├── format.json │ ├── items.json │ ├── maxItems.json │ ├── maxLength.json │ ├── maximum.json │ ├── minItems.json │ ├── minLength.json │ ├── minimum.json │ ├── optional │ │ ├── bignum.json │ │ ├── ecmascript-regex.json │ │ ├── format.json │ │ └── zeroTerminatedFloats.json │ ├── pattern.json │ ├── patternProperties.json │ ├── properties.json │ ├── ref.json │ ├── refRemote.json │ ├── required.json │ ├── type.json │ └── uniqueItems.json ├── draft4 │ ├── additionalItems.json │ ├── additionalProperties.json │ ├── allOf.json │ ├── anyOf.json │ ├── default.json │ ├── definitions.json │ ├── dependencies.json │ ├── enum.json │ ├── format.json │ ├── items.json │ ├── maxItems.json │ ├── maxLength.json │ ├── maxProperties.json │ ├── maximum.json │ ├── minItems.json │ ├── minLength.json │ ├── minProperties.json │ ├── minimum.json │ ├── multipleOf.json │ ├── not.json │ ├── oneOf.json │ ├── optional │ │ ├── bignum.json │ │ ├── ecmascript-regex.json │ │ ├── format.json │ │ └── zeroTerminatedFloats.json │ ├── pattern.json │ ├── patternProperties.json │ ├── properties.json │ ├── ref.json │ ├── refRemote.json │ ├── required.json │ ├── type.json │ └── uniqueItems.json ├── draft6 │ ├── additionalItems.json │ ├── additionalProperties.json │ ├── allOf.json │ ├── anyOf.json │ ├── boolean_schema.json │ ├── const.json │ ├── contains.json │ ├── default.json │ ├── definitions.json │ ├── dependencies.json │ ├── enum.json │ ├── exclusiveMaximum.json │ ├── exclusiveMinimum.json │ ├── format.json │ ├── items.json │ ├── maxItems.json │ ├── maxLength.json │ ├── maxProperties.json │ ├── maximum.json │ ├── minItems.json │ ├── minLength.json │ ├── minProperties.json │ ├── minimum.json │ ├── multipleOf.json │ ├── not.json │ ├── oneOf.json │ ├── optional │ │ ├── bignum.json │ │ ├── ecmascript-regex.json │ │ ├── format.json │ │ └── zeroTerminatedFloats.json │ ├── pattern.json │ ├── patternProperties.json │ ├── properties.json │ ├── propertyNames.json │ ├── ref.json │ ├── refRemote.json │ ├── required.json │ ├── type.json │ └── uniqueItems.json ├── draft7 │ ├── additionalItems.json │ ├── additionalProperties.json │ ├── allOf.json │ ├── anyOf.json │ ├── boolean_schema.json │ ├── const.json │ ├── contains.json │ ├── default.json │ ├── definitions.json │ ├── dependencies.json │ ├── enum.json │ ├── exclusiveMaximum.json │ ├── exclusiveMinimum.json │ ├── format.json │ ├── if-then-else.json │ ├── items.json │ ├── maxItems.json │ ├── maxLength.json │ ├── maxProperties.json │ ├── maximum.json │ ├── minItems.json │ ├── minLength.json │ ├── minProperties.json │ ├── minimum.json │ ├── multipleOf.json │ ├── not.json │ ├── oneOf.json │ ├── optional │ │ ├── bignum.json │ │ ├── content.json │ │ ├── ecmascript-regex.json │ │ ├── format │ │ │ ├── date-time.json │ │ │ ├── date.json │ │ │ ├── email.json │ │ │ ├── hostname.json │ │ │ ├── idn-email.json │ │ │ ├── idn-hostname.json │ │ │ ├── ipv4.json │ │ │ ├── ipv6.json │ │ │ ├── iri-reference.json │ │ │ ├── iri.json │ │ │ ├── json-pointer.json │ │ │ ├── regex.json │ │ │ ├── relative-json-pointer.json │ │ │ ├── time.json │ │ │ ├── uri-reference.json │ │ │ ├── uri-template.json │ │ │ └── uri.json │ │ └── zeroTerminatedFloats.json │ ├── pattern.json │ ├── patternProperties.json │ ├── properties.json │ ├── propertyNames.json │ ├── ref.json │ ├── refRemote.json │ ├── required.json │ ├── type.json │ └── uniqueItems.json ├── meta │ ├── applicator.json │ ├── content.json │ ├── core.json │ ├── format.json │ ├── hyper-schema.json │ ├── meta-data.json │ └── validation.json └── remotes │ ├── folder │ └── folderInteger.json │ ├── integer.json │ ├── name-defs.json │ ├── name.json │ ├── subSchemas-defs.json │ └── subSchemas.json ├── traversal.go ├── traversal_test.go ├── util.go └── validation_state.go /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | jobs: 3 | build: 4 | working_directory: /go/src/github.com/qri-io/jsonschema 5 | docker: 6 | - image: circleci/golang:1.13 7 | environment: 8 | GOLANG_ENV: test 9 | PORT: 3000 10 | environment: 11 | TEST_RESULTS: /tmp/test-results 12 | steps: 13 | - checkout 14 | - run: mkdir -p $TEST_RESULTS 15 | - run: go get github.com/jstemmer/go-junit-report golang.org/x/lint/golint github.com/sergi/go-diff/diffmatchpatch 16 | - run: 17 | name: Install deps 18 | command: > 19 | go get -v -d -u 20 | github.com/jstemmer/go-junit-report 21 | github.com/qri-io/jsonpointer 22 | - run: 23 | name: Run Lint Tests 24 | command: golint -set_exit_status ./... 25 | - run: 26 | name: Run Tests 27 | command: go test -v -race -coverprofile=coverage.txt -covermode=atomic 28 | - run: 29 | name: Publish coverage info to codecov.io 30 | command: bash <(curl -s https://codecov.io/bash) 31 | -------------------------------------------------------------------------------- /.circleci/cover.test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | echo "" > coverage.txt 5 | go test -v -race -coverprofile=profile.out -covermode=atomic github.com/qri-io/varName 6 | if [ -f profile.out ]; then 7 | cat profile.out >> coverage.txt 8 | rm profile.out 9 | fi -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribute 2 | 3 | qri is MIT licensed open source software. If you want to contribute, we're here to help you succeed. 4 | 5 | Please make sure to check out the [issues](https://github.com/qri-io/jsonschema/issues). Search the closed ones before reporting things, and (if you can!) help us with open ones. 6 | 7 | See Also 8 | - [Code of Conduct](https://github.com/qri-io/jsonschema/blob/master/code_of_conduct.md) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | coverage.txt 3 | .vscode -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Brendan O'Brien 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Let's keep all our changelog commands the same across all our packages: 2 | update-changelog: 3 | conventional-changelog -p angular -i CHANGELOG.md -s -------------------------------------------------------------------------------- /code_of_conduct.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | Online or off, we promote a harrassment-free environment for everyone, regardless of gender, gender identity and expression, sexual orientation, disability, physical appearance, body size, race, age or religion or technical skill level. We do not tolerate harassment of participants in any form. 4 | 5 | Harassment includes verbal comments that reinforce social structures of domination related to gender, gender identity and expression, sexual orientation, disability, physical appearance, body size, race, age, religion, sexual images in public spaces, deliberate intimidation, stalking, following, harassing photography or recording, sustained disruption of talks or other events, inappropriate physical contact, and unwelcome sexual attention. Participants asked to stop any harassing behavior are expected to comply immediately. 6 | 7 | If a participant engages in harassing behaviour, the organizers may take any action they deem appropriate, including warning the offender or expulsion from events and online forums. 8 | 9 | If you are being harassed, notice that someone else is being harassed, or have any other concerns, please contact a member of the organizing team immediately. 10 | 11 | At offline events, organizers will identify themselves, and will help participants contact venue security or local law enforcement, provide escorts, or otherwise assist those experiencing harassment to feel safe for the duration of the event. We value your participation! 12 | 13 | This document is based on a similar code from [EDGI](https://envirodatagov.org/) and [Civic Tech Toronto](http://civictech.ca/about-us/), itself derived from the [Recurse Center’s Social Rules](https://www.recurse.com/manual#sec-environment), and the [anti-harassment policy from the Geek Feminism Wiki](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy). -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | ci: 3 | - "ci/circle-ci" 4 | notify: 5 | require_ci_to_pass: no 6 | after_n_builds: 1 7 | coverage: 8 | range: "80...100" 9 | comment: off -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/qri-io/jsonschema 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/qri-io/jsonpointer v0.1.1 7 | github.com/sergi/go-diff v1.0.0 8 | github.com/stretchr/testify v1.3.0 // indirect 9 | ) 10 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 4 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 5 | github.com/qri-io/jsonpointer v0.1.1 h1:prVZBZLL6TW5vsSB9fFHFAMBLI4b0ri5vribQlTJiBA= 6 | github.com/qri-io/jsonpointer v0.1.1/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64= 7 | github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= 8 | github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 9 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 10 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 11 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 12 | -------------------------------------------------------------------------------- /schema_loader.go: -------------------------------------------------------------------------------- 1 | package jsonschema 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "io/ioutil" 8 | "net/http" 9 | "net/url" 10 | ) 11 | 12 | var lr *LoaderRegistry 13 | 14 | // LoaderRegistry maintains a lookup table between uri schemes and associated loader 15 | type LoaderRegistry struct { 16 | loaderLookup map[string]SchemaLoaderFunc 17 | } 18 | 19 | // SchemaLoaderFunc is a function that loads a schema for a specific URI Scheme 20 | type SchemaLoaderFunc func(ctx context.Context, uri *url.URL, schema *Schema) error 21 | 22 | // NewLoaderRegistry allocates a new schema loader registry 23 | func NewLoaderRegistry() *LoaderRegistry { 24 | r := &LoaderRegistry{ 25 | loaderLookup: map[string]SchemaLoaderFunc{}, 26 | } 27 | 28 | r.Register("http", HTTPSchemaLoader) 29 | r.Register("https", HTTPSchemaLoader) 30 | r.Register("file", FileSchemaLoader) 31 | 32 | return r 33 | } 34 | 35 | // Register a new schema loader for a specific URI Scheme 36 | func (r *LoaderRegistry) Register(scheme string, loader SchemaLoaderFunc) { 37 | r.loaderLookup[scheme] = loader 38 | } 39 | 40 | // Get the schema loader func for a specific URI Scheme 41 | func (r *LoaderRegistry) Get(scheme string) (SchemaLoaderFunc, bool) { 42 | l, exists := r.loaderLookup[scheme] 43 | return l, exists 44 | } 45 | 46 | // GetSchemaLoaderRegistry provides an accessor to a globally available (schema) loader registry 47 | func GetSchemaLoaderRegistry() *LoaderRegistry { 48 | if lr == nil { 49 | lr = NewLoaderRegistry() 50 | } 51 | return lr 52 | } 53 | 54 | // FetchSchema downloads and loads a schema from a remote location 55 | func FetchSchema(ctx context.Context, uri string, schema *Schema) error { 56 | schemaDebug(fmt.Sprintf("[FetchSchema] Fetching: %s", uri)) 57 | u, err := url.Parse(uri) 58 | if err != nil { 59 | return err 60 | } 61 | 62 | registry := GetSchemaLoaderRegistry() 63 | 64 | loader, exists := registry.Get(u.Scheme) 65 | 66 | if !exists { 67 | return fmt.Errorf("URI scheme %s is not supported for uri: %s", u.Scheme, uri) 68 | } 69 | 70 | return loader(ctx, u, schema) 71 | } 72 | 73 | // HTTPSchemaLoader loads a schema from a http or https URI 74 | func HTTPSchemaLoader(ctx context.Context, uri *url.URL, schema *Schema) error { 75 | var req *http.Request 76 | if ctx != nil { 77 | req, _ = http.NewRequestWithContext(ctx, "GET", uri.String(), nil) 78 | } else { 79 | req, _ = http.NewRequest("GET", uri.String(), nil) 80 | } 81 | client := &http.Client{} 82 | res, err := client.Do(req) 83 | if err != nil { 84 | return err 85 | } 86 | body, err := ioutil.ReadAll(res.Body) 87 | if err != nil { 88 | return err 89 | } 90 | if schema == nil { 91 | schema = &Schema{} 92 | } 93 | return json.Unmarshal(body, schema) 94 | } 95 | 96 | // FileSchemaLoader loads a schema from a file URI 97 | func FileSchemaLoader(ctx context.Context, uri *url.URL, schema *Schema) error { 98 | body, err := ioutil.ReadFile(uri.Path) 99 | if err != nil { 100 | return err 101 | } 102 | if schema == nil { 103 | schema = &Schema{} 104 | } 105 | return json.Unmarshal(body, schema) 106 | } 107 | -------------------------------------------------------------------------------- /schema_registry.go: -------------------------------------------------------------------------------- 1 | package jsonschema 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "strings" 7 | ) 8 | 9 | var sr *SchemaRegistry 10 | 11 | // SchemaRegistry maintains a lookup table between schema string references 12 | // and actual schemas 13 | type SchemaRegistry struct { 14 | schemaLookup map[string]*Schema 15 | contextLookup map[string]*Schema 16 | } 17 | 18 | // GetSchemaRegistry provides an accessor to a globally available schema registry 19 | func GetSchemaRegistry() *SchemaRegistry { 20 | if sr == nil { 21 | sr = &SchemaRegistry{ 22 | schemaLookup: map[string]*Schema{}, 23 | contextLookup: map[string]*Schema{}, 24 | } 25 | } 26 | return sr 27 | } 28 | 29 | // ResetSchemaRegistry resets the main SchemaRegistry 30 | func ResetSchemaRegistry() { 31 | sr = nil 32 | } 33 | 34 | // Get fetches a schema from the top level context registry or fetches it from a remote 35 | func (sr *SchemaRegistry) Get(ctx context.Context, uri string) *Schema { 36 | uri = strings.TrimRight(uri, "#") 37 | schema := sr.schemaLookup[uri] 38 | if schema == nil { 39 | fetchedSchema := &Schema{} 40 | err := FetchSchema(ctx, uri, fetchedSchema) 41 | if err != nil { 42 | schemaDebug(fmt.Sprintf("[SchemaRegistry] Fetch error: %s", err.Error())) 43 | return nil 44 | } 45 | if fetchedSchema == nil { 46 | return nil 47 | } 48 | fetchedSchema.docPath = uri 49 | // TODO(arqu): meta validate schema 50 | schema = fetchedSchema 51 | sr.schemaLookup[uri] = schema 52 | } 53 | return schema 54 | } 55 | 56 | // GetKnown fetches a schema from the top level context registry 57 | func (sr *SchemaRegistry) GetKnown(uri string) *Schema { 58 | uri = strings.TrimRight(uri, "#") 59 | return sr.schemaLookup[uri] 60 | } 61 | 62 | // GetLocal fetches a schema from the local context registry 63 | func (sr *SchemaRegistry) GetLocal(uri string) *Schema { 64 | uri = strings.TrimRight(uri, "#") 65 | return sr.contextLookup[uri] 66 | } 67 | 68 | // Register registers a schema to the top level context 69 | func (sr *SchemaRegistry) Register(sch *Schema) { 70 | if sch.docPath == "" { 71 | return 72 | } 73 | sr.schemaLookup[sch.docPath] = sch 74 | } 75 | 76 | // RegisterLocal registers a schema to a local context 77 | func (sr *SchemaRegistry) RegisterLocal(sch *Schema) { 78 | if sch.id != "" && IsLocalSchemaID(sch.id) { 79 | sr.contextLookup[sch.id] = sch 80 | } 81 | 82 | if sch.HasKeyword("$anchor") { 83 | anchorKeyword := sch.keywords["$anchor"].(*Anchor) 84 | anchorURI := sch.docPath + "#" + string(*anchorKeyword) 85 | if sr.contextLookup == nil { 86 | sr.contextLookup = map[string]*Schema{} 87 | } 88 | sr.contextLookup[anchorURI] = sch 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /testdata/coding/arrays.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": 1, 3 | "additionalItems": 3, 4 | "maxItems": 2, 5 | "minItems": 1, 6 | "uniqueItems": {} 7 | } -------------------------------------------------------------------------------- /testdata/coding/booleans.json: -------------------------------------------------------------------------------- 1 | { 2 | "allOf": [ 3 | false 4 | ], 5 | "anyOf": [ 6 | {} 7 | ], 8 | "not": false, 9 | "oneOf": [ 10 | true 11 | ] 12 | } -------------------------------------------------------------------------------- /testdata/coding/conditionals.json: -------------------------------------------------------------------------------- 1 | { 2 | "else": false, 3 | "if": {}, 4 | "then": {} 5 | } -------------------------------------------------------------------------------- /testdata/coding/false.json: -------------------------------------------------------------------------------- 1 | false -------------------------------------------------------------------------------- /testdata/coding/numeric.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclusiveMaximum": 5, 3 | "exclusiveMinimum": 7, 4 | "maximum": 2, 5 | "minimum": 6, 6 | "multipleOf": 4 7 | } -------------------------------------------------------------------------------- /testdata/coding/objects.json: -------------------------------------------------------------------------------- 1 | { 2 | "additionalProperties": {}, 3 | "dependentRequired": { 4 | "foo": [ 5 | "bar", 6 | "baz" 7 | ] 8 | }, 9 | "dependentSchemas": { 10 | "bat": false 11 | }, 12 | "maxProperties": 1, 13 | "minProperties": 2, 14 | "patternProperties": {}, 15 | "properties": {}, 16 | "propertyNames": false, 17 | "required": [ 18 | "foo", 19 | "bar" 20 | ] 21 | } -------------------------------------------------------------------------------- /testdata/coding/std.json: -------------------------------------------------------------------------------- 1 | { 2 | "const": "2", 3 | "enum": [ 4 | "a", 5 | 1, 6 | "c", 7 | "b", 8 | { 9 | "foo": "bar" 10 | }, 11 | false 12 | ], 13 | "type": "integer" 14 | } -------------------------------------------------------------------------------- /testdata/coding/strings.json: -------------------------------------------------------------------------------- 1 | { 2 | "maxLength": 1, 3 | "minLength": 2, 4 | "pattern": "$string/" 5 | } -------------------------------------------------------------------------------- /testdata/coding/true.json: -------------------------------------------------------------------------------- 1 | true -------------------------------------------------------------------------------- /testdata/draft2019-09/additionalItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "additionalItems as schema", 4 | "schema": { 5 | "items": [{}], 6 | "additionalItems": {"type": "integer"} 7 | }, 8 | "tests": [ 9 | { 10 | "description": "additional items match schema", 11 | "data": [ null, 2, 3, 4 ], 12 | "valid": true 13 | }, 14 | { 15 | "description": "additional items do not match schema", 16 | "data": [ null, 2, 3, "foo" ], 17 | "valid": false 18 | } 19 | ] 20 | }, 21 | { 22 | "description": "items is schema, no additionalItems", 23 | "schema": { 24 | "items": {}, 25 | "additionalItems": false 26 | }, 27 | "tests": [ 28 | { 29 | "description": "all items match schema", 30 | "data": [ 1, 2, 3, 4, 5 ], 31 | "valid": true 32 | } 33 | ] 34 | }, 35 | { 36 | "description": "array of items with no additionalItems", 37 | "schema": { 38 | "items": [{}, {}, {}], 39 | "additionalItems": false 40 | }, 41 | "tests": [ 42 | { 43 | "description": "fewer number of items present", 44 | "data": [ 1, 2 ], 45 | "valid": true 46 | }, 47 | { 48 | "description": "equal number of items present", 49 | "data": [ 1, 2, 3 ], 50 | "valid": true 51 | }, 52 | { 53 | "description": "additional items are not permitted", 54 | "data": [ 1, 2, 3, 4 ], 55 | "valid": false 56 | } 57 | ] 58 | }, 59 | { 60 | "description": "additionalItems as false without items", 61 | "schema": {"additionalItems": false}, 62 | "tests": [ 63 | { 64 | "description": 65 | "items defaults to empty schema so everything is valid", 66 | "data": [ 1, 2, 3, 4, 5 ], 67 | "valid": true 68 | }, 69 | { 70 | "description": "ignores non-arrays", 71 | "data": {"foo" : "bar"}, 72 | "valid": true 73 | } 74 | ] 75 | }, 76 | { 77 | "description": "additionalItems are allowed by default", 78 | "schema": {"items": [{"type": "integer"}]}, 79 | "tests": [ 80 | { 81 | "description": "only the first item is validated", 82 | "data": [1, "foo", false], 83 | "valid": true 84 | } 85 | ] 86 | } 87 | ] 88 | -------------------------------------------------------------------------------- /testdata/draft2019-09/anchor.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "Location-independent identifier", 4 | "schema": { 5 | "allOf": [{ 6 | "$ref": "#foo" 7 | }], 8 | "$defs": { 9 | "A": { 10 | "$anchor": "foo", 11 | "type": "integer" 12 | } 13 | } 14 | }, 15 | "tests": [ 16 | { 17 | "data": 1, 18 | "description": "match", 19 | "valid": true 20 | }, 21 | { 22 | "data": "a", 23 | "description": "mismatch", 24 | "valid": false 25 | } 26 | ] 27 | }, 28 | { 29 | "description": "Location-independent identifier with absolute URI", 30 | "schema": { 31 | "allOf": [{ 32 | "$ref": "http://localhost:1234/bar#foo" 33 | }], 34 | "$defs": { 35 | "A": { 36 | "$id": "http://localhost:1234/bar", 37 | "$anchor": "foo", 38 | "type": "integer" 39 | } 40 | } 41 | }, 42 | "tests": [ 43 | { 44 | "data": 1, 45 | "description": "match", 46 | "valid": true 47 | }, 48 | { 49 | "data": "a", 50 | "description": "mismatch", 51 | "valid": false 52 | } 53 | ] 54 | }, 55 | { 56 | "description": "Location-independent identifier with base URI change in subschema", 57 | "schema": { 58 | "$id": "http://localhost:1234/root", 59 | "allOf": [{ 60 | "$ref": "http://localhost:1234/nested.json#foo" 61 | }], 62 | "$defs": { 63 | "A": { 64 | "$id": "nested.json", 65 | "$defs": { 66 | "B": { 67 | "$anchor": "foo", 68 | "type": "integer" 69 | } 70 | } 71 | } 72 | } 73 | }, 74 | "tests": [ 75 | { 76 | "data": 1, 77 | "description": "match", 78 | "valid": true 79 | }, 80 | { 81 | "data": "a", 82 | "description": "mismatch", 83 | "valid": false 84 | } 85 | ] 86 | } 87 | ] 88 | -------------------------------------------------------------------------------- /testdata/draft2019-09/contains.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "contains keyword validation", 4 | "schema": { 5 | "contains": {"minimum": 5} 6 | }, 7 | "tests": [ 8 | { 9 | "description": "array with item matching schema (5) is valid", 10 | "data": [3, 4, 5], 11 | "valid": true 12 | }, 13 | { 14 | "description": "array with item matching schema (6) is valid", 15 | "data": [3, 4, 6], 16 | "valid": true 17 | }, 18 | { 19 | "description": "array with two items matching schema (5, 6) is valid", 20 | "data": [3, 4, 5, 6], 21 | "valid": true 22 | }, 23 | { 24 | "description": "array without items matching schema is invalid", 25 | "data": [2, 3, 4], 26 | "valid": false 27 | }, 28 | { 29 | "description": "empty array is invalid", 30 | "data": [], 31 | "valid": false 32 | }, 33 | { 34 | "description": "not array is valid", 35 | "data": {}, 36 | "valid": true 37 | } 38 | ] 39 | }, 40 | { 41 | "description": "contains keyword with const keyword", 42 | "schema": { 43 | "contains": { "const": 5 } 44 | }, 45 | "tests": [ 46 | { 47 | "description": "array with item 5 is valid", 48 | "data": [3, 4, 5], 49 | "valid": true 50 | }, 51 | { 52 | "description": "array with two items 5 is valid", 53 | "data": [3, 4, 5, 5], 54 | "valid": true 55 | }, 56 | { 57 | "description": "array without item 5 is invalid", 58 | "data": [1, 2, 3, 4], 59 | "valid": false 60 | } 61 | ] 62 | }, 63 | { 64 | "description": "contains keyword with boolean schema true", 65 | "schema": {"contains": true}, 66 | "tests": [ 67 | { 68 | "description": "any non-empty array is valid", 69 | "data": ["foo"], 70 | "valid": true 71 | }, 72 | { 73 | "description": "empty array is invalid", 74 | "data": [], 75 | "valid": false 76 | } 77 | ] 78 | }, 79 | { 80 | "description": "contains keyword with boolean schema false", 81 | "schema": {"contains": false}, 82 | "tests": [ 83 | { 84 | "description": "any non-empty array is invalid", 85 | "data": ["foo"], 86 | "valid": false 87 | }, 88 | { 89 | "description": "empty array is invalid", 90 | "data": [], 91 | "valid": false 92 | } 93 | ] 94 | } 95 | ] 96 | -------------------------------------------------------------------------------- /testdata/draft2019-09/default.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "invalid type for default", 4 | "schema": { 5 | "properties": { 6 | "foo": { 7 | "type": "integer", 8 | "default": [] 9 | } 10 | } 11 | }, 12 | "tests": [ 13 | { 14 | "description": "valid when property is specified", 15 | "data": {"foo": 13}, 16 | "valid": true 17 | }, 18 | { 19 | "description": "still valid when the invalid default is used", 20 | "data": {}, 21 | "valid": true 22 | } 23 | ] 24 | }, 25 | { 26 | "description": "invalid string value for default", 27 | "schema": { 28 | "properties": { 29 | "bar": { 30 | "type": "string", 31 | "minLength": 4, 32 | "default": "bad" 33 | } 34 | } 35 | }, 36 | "tests": [ 37 | { 38 | "description": "valid when property is specified", 39 | "data": {"bar": "good"}, 40 | "valid": true 41 | }, 42 | { 43 | "description": "still valid when the invalid default is used", 44 | "data": {}, 45 | "valid": true 46 | } 47 | ] 48 | } 49 | ] 50 | -------------------------------------------------------------------------------- /testdata/draft2019-09/defs.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "valid definition", 4 | "schema": {"$ref": "https://json-schema.org/draft/2019-09/schema"}, 5 | "tests": [ 6 | { 7 | "description": "valid definition schema", 8 | "data": {"$defs": {"foo": {"type": "integer"}}}, 9 | "valid": true 10 | } 11 | ] 12 | }, 13 | { 14 | "description": "invalid definition", 15 | "schema": {"$ref": "https://json-schema.org/draft/2019-09/schema"}, 16 | "tests": [ 17 | { 18 | "description": "invalid definition schema", 19 | "data": {"$defs": {"foo": {"type": 1}}}, 20 | "valid": false 21 | } 22 | ] 23 | } 24 | ] 25 | -------------------------------------------------------------------------------- /testdata/draft2019-09/exclusiveMaximum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "exclusiveMaximum validation", 4 | "schema": { 5 | "exclusiveMaximum": 3.0 6 | }, 7 | "tests": [ 8 | { 9 | "description": "below the exclusiveMaximum is valid", 10 | "data": 2.2, 11 | "valid": true 12 | }, 13 | { 14 | "description": "boundary point is invalid", 15 | "data": 3.0, 16 | "valid": false 17 | }, 18 | { 19 | "description": "above the exclusiveMaximum is invalid", 20 | "data": 3.5, 21 | "valid": false 22 | }, 23 | { 24 | "description": "ignores non-numbers", 25 | "data": "x", 26 | "valid": true 27 | } 28 | ] 29 | } 30 | ] 31 | -------------------------------------------------------------------------------- /testdata/draft2019-09/exclusiveMinimum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "exclusiveMinimum validation", 4 | "schema": { 5 | "exclusiveMinimum": 1.1 6 | }, 7 | "tests": [ 8 | { 9 | "description": "above the exclusiveMinimum is valid", 10 | "data": 1.2, 11 | "valid": true 12 | }, 13 | { 14 | "description": "boundary point is invalid", 15 | "data": 1.1, 16 | "valid": false 17 | }, 18 | { 19 | "description": "below the exclusiveMinimum is invalid", 20 | "data": 0.6, 21 | "valid": false 22 | }, 23 | { 24 | "description": "ignores non-numbers", 25 | "data": "x", 26 | "valid": true 27 | } 28 | ] 29 | } 30 | ] 31 | -------------------------------------------------------------------------------- /testdata/draft2019-09/maxItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxItems validation", 4 | "schema": {"maxItems": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": [1], 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": [1, 2], 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": [1, 2, 3], 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-arrays", 23 | "data": "foobar", 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /testdata/draft2019-09/maxLength.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxLength validation", 4 | "schema": {"maxLength": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": "f", 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": "fo", 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": "foo", 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-strings", 23 | "data": 100, 24 | "valid": true 25 | }, 26 | { 27 | "description": "two supplementary Unicode code points is long enough", 28 | "data": "\uD83D\uDCA9\uD83D\uDCA9", 29 | "valid": true 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /testdata/draft2019-09/maxProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxProperties validation", 4 | "schema": {"maxProperties": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": {"foo": 1}, 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": {"foo": 1, "bar": 2}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": {"foo": 1, "bar": 2, "baz": 3}, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores arrays", 23 | "data": [1, 2, 3], 24 | "valid": true 25 | }, 26 | { 27 | "description": "ignores strings", 28 | "data": "foobar", 29 | "valid": true 30 | }, 31 | { 32 | "description": "ignores other non-objects", 33 | "data": 12, 34 | "valid": true 35 | } 36 | ] 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /testdata/draft2019-09/maximum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maximum validation", 4 | "schema": {"maximum": 3.0}, 5 | "tests": [ 6 | { 7 | "description": "below the maximum is valid", 8 | "data": 2.6, 9 | "valid": true 10 | }, 11 | { 12 | "description": "boundary point is valid", 13 | "data": 3.0, 14 | "valid": true 15 | }, 16 | { 17 | "description": "above the maximum is invalid", 18 | "data": 3.5, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-numbers", 23 | "data": "x", 24 | "valid": true 25 | } 26 | ] 27 | }, 28 | { 29 | "description": "maximum validation with unsigned integer", 30 | "schema": {"maximum": 300}, 31 | "tests": [ 32 | { 33 | "description": "below the maximum is invalid", 34 | "data": 299.97, 35 | "valid": true 36 | }, 37 | { 38 | "description": "boundary point integer is valid", 39 | "data": 300, 40 | "valid": true 41 | }, 42 | { 43 | "description": "boundary point float is valid", 44 | "data": 300.00, 45 | "valid": true 46 | }, 47 | { 48 | "description": "above the maximum is invalid", 49 | "data": 300.5, 50 | "valid": false 51 | } 52 | ] 53 | } 54 | ] 55 | -------------------------------------------------------------------------------- /testdata/draft2019-09/minItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minItems validation", 4 | "schema": {"minItems": 1}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": [1, 2], 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": [1], 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": [], 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-arrays", 23 | "data": "", 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /testdata/draft2019-09/minLength.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minLength validation", 4 | "schema": {"minLength": 2}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": "foo", 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": "fo", 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": "f", 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-strings", 23 | "data": 1, 24 | "valid": true 25 | }, 26 | { 27 | "description": "one supplementary Unicode code point is not long enough", 28 | "data": "\uD83D\uDCA9", 29 | "valid": false 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /testdata/draft2019-09/minProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minProperties validation", 4 | "schema": {"minProperties": 1}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": {"foo": 1, "bar": 2}, 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": {"foo": 1}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": {}, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores arrays", 23 | "data": [], 24 | "valid": true 25 | }, 26 | { 27 | "description": "ignores strings", 28 | "data": "", 29 | "valid": true 30 | }, 31 | { 32 | "description": "ignores other non-objects", 33 | "data": 12, 34 | "valid": true 35 | } 36 | ] 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /testdata/draft2019-09/minimum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minimum validation", 4 | "schema": {"minimum": 1.1}, 5 | "tests": [ 6 | { 7 | "description": "above the minimum is valid", 8 | "data": 2.6, 9 | "valid": true 10 | }, 11 | { 12 | "description": "boundary point is valid", 13 | "data": 1.1, 14 | "valid": true 15 | }, 16 | { 17 | "description": "below the minimum is invalid", 18 | "data": 0.6, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-numbers", 23 | "data": "x", 24 | "valid": true 25 | } 26 | ] 27 | }, 28 | { 29 | "description": "minimum validation with signed integer", 30 | "schema": {"minimum": -2}, 31 | "tests": [ 32 | { 33 | "description": "negative above the minimum is valid", 34 | "data": -1, 35 | "valid": true 36 | }, 37 | { 38 | "description": "positive above the minimum is valid", 39 | "data": 0, 40 | "valid": true 41 | }, 42 | { 43 | "description": "boundary point is valid", 44 | "data": -2, 45 | "valid": true 46 | }, 47 | { 48 | "description": "boundary point with float is valid", 49 | "data": -2.0, 50 | "valid": true 51 | }, 52 | { 53 | "description": "float below the minimum is invalid", 54 | "data": -2.0001, 55 | "valid": false 56 | }, 57 | { 58 | "description": "int below the minimum is invalid", 59 | "data": -3, 60 | "valid": false 61 | }, 62 | { 63 | "description": "ignores non-numbers", 64 | "data": "x", 65 | "valid": true 66 | } 67 | ] 68 | } 69 | ] 70 | -------------------------------------------------------------------------------- /testdata/draft2019-09/multipleOf.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "by int", 4 | "schema": {"multipleOf": 2}, 5 | "tests": [ 6 | { 7 | "description": "int by int", 8 | "data": 10, 9 | "valid": true 10 | }, 11 | { 12 | "description": "int by int fail", 13 | "data": 7, 14 | "valid": false 15 | }, 16 | { 17 | "description": "ignores non-numbers", 18 | "data": "foo", 19 | "valid": true 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "by number", 25 | "schema": {"multipleOf": 1.5}, 26 | "tests": [ 27 | { 28 | "description": "zero is multiple of anything", 29 | "data": 0, 30 | "valid": true 31 | }, 32 | { 33 | "description": "4.5 is multiple of 1.5", 34 | "data": 4.5, 35 | "valid": true 36 | }, 37 | { 38 | "description": "35 is not multiple of 1.5", 39 | "data": 35, 40 | "valid": false 41 | } 42 | ] 43 | }, 44 | { 45 | "description": "by small number", 46 | "schema": {"multipleOf": 0.0001}, 47 | "tests": [ 48 | { 49 | "description": "0.0075 is multiple of 0.0001", 50 | "data": 0.0075, 51 | "valid": true 52 | }, 53 | { 54 | "description": "0.00751 is not multiple of 0.0001", 55 | "data": 0.00751, 56 | "valid": false 57 | } 58 | ] 59 | } 60 | ] 61 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/content.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of string-encoded content based on media type", 4 | "schema": { 5 | "contentMediaType": "application/json" 6 | }, 7 | "tests": [ 8 | { 9 | "description": "a valid JSON document", 10 | "data": "{\"foo\": \"bar\"}", 11 | "valid": true 12 | }, 13 | { 14 | "description": "an invalid JSON document", 15 | "data": "{:}", 16 | "valid": false 17 | }, 18 | { 19 | "description": "ignores non-strings", 20 | "data": 100, 21 | "valid": true 22 | } 23 | ] 24 | }, 25 | { 26 | "description": "validation of binary string-encoding", 27 | "schema": { 28 | "contentEncoding": "base64" 29 | }, 30 | "tests": [ 31 | { 32 | "description": "a valid base64 string", 33 | "data": "eyJmb28iOiAiYmFyIn0K", 34 | "valid": true 35 | }, 36 | { 37 | "description": "an invalid base64 string (% is not a valid character)", 38 | "data": "eyJmb28iOi%iYmFyIn0K", 39 | "valid": false 40 | }, 41 | { 42 | "description": "ignores non-strings", 43 | "data": 100, 44 | "valid": true 45 | } 46 | ] 47 | }, 48 | { 49 | "description": "validation of binary-encoded media type documents", 50 | "schema": { 51 | "contentMediaType": "application/json", 52 | "contentEncoding": "base64" 53 | }, 54 | "tests": [ 55 | { 56 | "description": "a valid base64-encoded JSON document", 57 | "data": "eyJmb28iOiAiYmFyIn0K", 58 | "valid": true 59 | }, 60 | { 61 | "description": "a validly-encoded invalid JSON document", 62 | "data": "ezp9Cg==", 63 | "valid": false 64 | }, 65 | { 66 | "description": "an invalid base64 string that is valid JSON", 67 | "data": "{}", 68 | "valid": false 69 | }, 70 | { 71 | "description": "ignores non-strings", 72 | "data": 100, 73 | "valid": true 74 | } 75 | ] 76 | } 77 | ] 78 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/format/date-time.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of date-time strings", 4 | "schema": {"format": "date-time"}, 5 | "tests": [ 6 | { 7 | "description": "a valid date-time string", 8 | "data": "1963-06-19T08:30:06.283185Z", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a valid date-time string without second fraction", 13 | "data": "1963-06-19T08:30:06Z", 14 | "valid": true 15 | }, 16 | { 17 | "description": "a valid date-time string with plus offset", 18 | "data": "1937-01-01T12:00:27.87+00:20", 19 | "valid": true 20 | }, 21 | { 22 | "description": "a valid date-time string with minus offset", 23 | "data": "1990-12-31T15:59:50.123-08:00", 24 | "valid": true 25 | }, 26 | { 27 | "description": "a invalid day in date-time string", 28 | "data": "1990-02-31T15:59:60.123-08:00", 29 | "valid": false 30 | }, 31 | { 32 | "description": "an invalid offset in date-time string", 33 | "data": "1990-12-31T15:59:60-24:00", 34 | "valid": false 35 | }, 36 | { 37 | "description": "an invalid date-time string", 38 | "data": "06/19/1963 08:30:06 PST", 39 | "valid": false 40 | }, 41 | { 42 | "description": "case-insensitive T and Z", 43 | "data": "1963-06-19t08:30:06.283185z", 44 | "valid": true 45 | }, 46 | { 47 | "description": "only RFC3339 not all of ISO 8601 are valid", 48 | "data": "2013-350T01:01:01", 49 | "valid": false 50 | } 51 | ] 52 | } 53 | ] 54 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/format/date.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of date strings", 4 | "schema": {"format": "date"}, 5 | "tests": [ 6 | { 7 | "description": "a valid date string", 8 | "data": "1963-06-19", 9 | "valid": true 10 | }, 11 | { 12 | "description": "an invalid date-time string", 13 | "data": "06/19/1963", 14 | "valid": false 15 | }, 16 | { 17 | "description": "only RFC3339 not all of ISO 8601 are valid", 18 | "data": "2013-350", 19 | "valid": false 20 | } 21 | ] 22 | } 23 | ] 24 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/format/email.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of e-mail addresses", 4 | "schema": {"format": "email"}, 5 | "tests": [ 6 | { 7 | "description": "a valid e-mail address", 8 | "data": "joe.bloggs@example.com", 9 | "valid": true 10 | }, 11 | { 12 | "description": "an invalid e-mail address", 13 | "data": "2962", 14 | "valid": false 15 | } 16 | ] 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/format/hostname.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of host names", 4 | "schema": {"format": "hostname"}, 5 | "tests": [ 6 | { 7 | "description": "a valid host name", 8 | "data": "www.example.com", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a valid punycoded IDN hostname", 13 | "data": "xn--4gbwdl.xn--wgbh1c", 14 | "valid": true 15 | }, 16 | { 17 | "description": "a host name starting with an illegal character", 18 | "data": "-a-host-name-that-starts-with--", 19 | "valid": false 20 | }, 21 | { 22 | "description": "a host name containing illegal characters", 23 | "data": "not_a_valid_host_name", 24 | "valid": false 25 | }, 26 | { 27 | "description": "a host name with a component too long", 28 | "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component", 29 | "valid": false 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/format/idn-email.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of an internationalized e-mail addresses", 4 | "schema": {"format": "idn-email"}, 5 | "tests": [ 6 | { 7 | "description": "a valid idn e-mail (example@example.test in Hangul)", 8 | "data": "실례@실례.테스트", 9 | "valid": true 10 | }, 11 | { 12 | "description": "an invalid idn e-mail address", 13 | "data": "2962", 14 | "valid": false 15 | } 16 | ] 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/format/idn-hostname.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of internationalized host names", 4 | "schema": {"format": "idn-hostname"}, 5 | "tests": [ 6 | { 7 | "description": "a valid host name (example.test in Hangul)", 8 | "data": "실례.테스트", 9 | "valid": true 10 | }, 11 | { 12 | "description": "illegal first char U+302E Hangul single dot tone mark", 13 | "data": "〮실례.테스트", 14 | "valid": false 15 | }, 16 | { 17 | "description": "contains illegal char U+302E Hangul single dot tone mark", 18 | "data": "실〮례.테스트", 19 | "valid": false 20 | }, 21 | { 22 | "description": "a host name with a component too long", 23 | "data": "실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실례례테스트례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례테스트례례실례.테스트", 24 | "valid": false 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/format/ipv4.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of IP addresses", 4 | "schema": {"format": "ipv4"}, 5 | "tests": [ 6 | { 7 | "description": "a valid IP address", 8 | "data": "192.168.0.1", 9 | "valid": true 10 | }, 11 | { 12 | "description": "an IP address with too many components", 13 | "data": "127.0.0.0.1", 14 | "valid": false 15 | }, 16 | { 17 | "description": "an IP address with out-of-range values", 18 | "data": "256.256.256.256", 19 | "valid": false 20 | }, 21 | { 22 | "description": "an IP address without 4 components", 23 | "data": "127.0", 24 | "valid": false 25 | }, 26 | { 27 | "description": "an IP address as an integer", 28 | "data": "0x7f000001", 29 | "valid": false 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/format/ipv6.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of IPv6 addresses", 4 | "schema": {"format": "ipv6"}, 5 | "tests": [ 6 | { 7 | "description": "a valid IPv6 address", 8 | "data": "::1", 9 | "valid": true 10 | }, 11 | { 12 | "description": "an IPv6 address with out-of-range values", 13 | "data": "12345::", 14 | "valid": false 15 | }, 16 | { 17 | "description": "an IPv6 address with too many components", 18 | "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1", 19 | "valid": false 20 | }, 21 | { 22 | "description": "an IPv6 address containing illegal characters", 23 | "data": "::laptop", 24 | "valid": false 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/format/iri-reference.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of IRI References", 4 | "schema": {"format": "iri-reference"}, 5 | "tests": [ 6 | { 7 | "description": "a valid IRI", 8 | "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a valid protocol-relative IRI Reference", 13 | "data": "//ƒøø.ßår/?∂éœ=πîx#πîüx", 14 | "valid": true 15 | }, 16 | { 17 | "description": "a valid relative IRI Reference", 18 | "data": "/âππ", 19 | "valid": true 20 | }, 21 | { 22 | "description": "an invalid IRI Reference", 23 | "data": "\\\\WINDOWS\\filëßåré", 24 | "valid": false 25 | }, 26 | { 27 | "description": "a valid IRI Reference", 28 | "data": "âππ", 29 | "valid": true 30 | }, 31 | { 32 | "description": "a valid IRI fragment", 33 | "data": "#ƒrägmênt", 34 | "valid": true 35 | }, 36 | { 37 | "description": "an invalid IRI fragment", 38 | "data": "#ƒräg\\mênt", 39 | "valid": false 40 | } 41 | ] 42 | } 43 | ] 44 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/format/iri.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of IRIs", 4 | "schema": {"format": "iri"}, 5 | "tests": [ 6 | { 7 | "description": "a valid IRI with anchor tag", 8 | "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a valid IRI with anchor tag and parantheses", 13 | "data": "http://ƒøø.com/blah_(wîkïpédiå)_blah#ßité-1", 14 | "valid": true 15 | }, 16 | { 17 | "description": "a valid IRI with URL-encoded stuff", 18 | "data": "http://ƒøø.ßår/?q=Test%20URL-encoded%20stuff", 19 | "valid": true 20 | }, 21 | { 22 | "description": "a valid IRI with many special characters", 23 | "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com", 24 | "valid": true 25 | }, 26 | { 27 | "description": "a valid IRI based on IPv6", 28 | "data": "http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]", 29 | "valid": true 30 | }, 31 | { 32 | "description": "an invalid IRI based on IPv6", 33 | "data": "http://2001:0db8:85a3:0000:0000:8a2e:0370:7334", 34 | "valid": false 35 | }, 36 | { 37 | "description": "an invalid relative IRI Reference", 38 | "data": "/abc", 39 | "valid": false 40 | }, 41 | { 42 | "description": "an invalid IRI", 43 | "data": "\\\\WINDOWS\\filëßåré", 44 | "valid": false 45 | }, 46 | { 47 | "description": "an invalid IRI though valid IRI reference", 48 | "data": "âππ", 49 | "valid": false 50 | } 51 | ] 52 | } 53 | ] 54 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/format/regex.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of regular expressions", 4 | "schema": {"format": "regex"}, 5 | "tests": [ 6 | { 7 | "description": "a valid regular expression", 8 | "data": "([abc])+\\s+$", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a regular expression with unclosed parens is invalid", 13 | "data": "^(abc]", 14 | "valid": false 15 | } 16 | ] 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/format/relative-json-pointer.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of Relative JSON Pointers (RJP)", 4 | "schema": {"format": "relative-json-pointer"}, 5 | "tests": [ 6 | { 7 | "description": "a valid upwards RJP", 8 | "data": "1", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a valid downwards RJP", 13 | "data": "0/foo/bar", 14 | "valid": true 15 | }, 16 | { 17 | "description": "a valid up and then down RJP, with array index", 18 | "data": "2/0/baz/1/zip", 19 | "valid": true 20 | }, 21 | { 22 | "description": "a valid RJP taking the member or index name", 23 | "data": "0#", 24 | "valid": true 25 | }, 26 | { 27 | "description": "an invalid RJP that is a valid JSON Pointer", 28 | "data": "/foo/bar", 29 | "valid": false 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/format/time.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of time strings", 4 | "schema": {"format": "time"}, 5 | "tests": [ 6 | { 7 | "description": "a valid time string", 8 | "data": "08:30:06.283185Z", 9 | "valid": true 10 | }, 11 | { 12 | "description": "an invalid time string", 13 | "data": "08:30:06 PST", 14 | "valid": false 15 | }, 16 | { 17 | "description": "only RFC3339 not all of ISO 8601 are valid", 18 | "data": "01:01:01,1111", 19 | "valid": false 20 | } 21 | ] 22 | } 23 | ] 24 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/format/uri-reference.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of URI References", 4 | "schema": {"format": "uri-reference"}, 5 | "tests": [ 6 | { 7 | "description": "a valid URI", 8 | "data": "http://foo.bar/?baz=qux#quux", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a valid protocol-relative URI Reference", 13 | "data": "//foo.bar/?baz=qux#quux", 14 | "valid": true 15 | }, 16 | { 17 | "description": "a valid relative URI Reference", 18 | "data": "/abc", 19 | "valid": true 20 | }, 21 | { 22 | "description": "an invalid URI Reference", 23 | "data": "\\\\WINDOWS\\fileshare", 24 | "valid": false 25 | }, 26 | { 27 | "description": "a valid URI Reference", 28 | "data": "abc", 29 | "valid": true 30 | }, 31 | { 32 | "description": "a valid URI fragment", 33 | "data": "#fragment", 34 | "valid": true 35 | }, 36 | { 37 | "description": "an invalid URI fragment", 38 | "data": "#frag\\ment", 39 | "valid": false 40 | } 41 | ] 42 | } 43 | ] 44 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/format/uri-template.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "format: uri-template", 4 | "schema": {"format": "uri-template"}, 5 | "tests": [ 6 | { 7 | "description": "a valid uri-template", 8 | "data": "http://example.com/dictionary/{term:1}/{term}", 9 | "valid": true 10 | }, 11 | { 12 | "description": "an invalid uri-template", 13 | "data": "http://example.com/dictionary/{term:1}/{term", 14 | "valid": false 15 | }, 16 | { 17 | "description": "a valid uri-template without variables", 18 | "data": "http://example.com/dictionary", 19 | "valid": true 20 | }, 21 | { 22 | "description": "a valid relative uri-template", 23 | "data": "dictionary/{term:1}/{term}", 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/refOfUnknownKeyword.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "reference of a root arbitrary keyword ", 4 | "schema": { 5 | "unknown-keyword": {"type": "integer"}, 6 | "properties": { 7 | "bar": {"$ref": "#/unknown-keyword"} 8 | } 9 | }, 10 | "tests": [ 11 | { 12 | "description": "match", 13 | "data": {"bar": 3}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "mismatch", 18 | "data": {"bar": true}, 19 | "valid": false 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "reference of an arbitrary keyword of a sub-schema", 25 | "schema": { 26 | "properties": { 27 | "foo": {"unknown-keyword": {"type": "integer"}}, 28 | "bar": {"$ref": "#/properties/foo/unknown-keyword"} 29 | } 30 | }, 31 | "tests": [ 32 | { 33 | "description": "match", 34 | "data": {"bar": 3}, 35 | "valid": true 36 | }, 37 | { 38 | "description": "mismatch", 39 | "data": {"bar": true}, 40 | "valid": false 41 | } 42 | ] 43 | } 44 | ] 45 | -------------------------------------------------------------------------------- /testdata/draft2019-09/optional/zeroTerminatedFloats.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "some languages do not distinguish between different types of numeric value", 4 | "schema": { 5 | "type": "integer" 6 | }, 7 | "tests": [ 8 | { 9 | "description": "a float without fractional part is an integer", 10 | "data": 1.0, 11 | "valid": true 12 | } 13 | ] 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /testdata/draft2019-09/pattern.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "pattern validation", 4 | "schema": {"pattern": "^a*$"}, 5 | "tests": [ 6 | { 7 | "description": "a matching pattern is valid", 8 | "data": "aaa", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a non-matching pattern is invalid", 13 | "data": "abc", 14 | "valid": false 15 | }, 16 | { 17 | "description": "ignores non-strings", 18 | "data": true, 19 | "valid": true 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "pattern is not anchored", 25 | "schema": {"pattern": "a+"}, 26 | "tests": [ 27 | { 28 | "description": "matches a substring", 29 | "data": "xxaayy", 30 | "valid": true 31 | } 32 | ] 33 | } 34 | ] 35 | -------------------------------------------------------------------------------- /testdata/draft2019-09/propertyNames.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "propertyNames validation", 4 | "schema": { 5 | "propertyNames": {"maxLength": 3} 6 | }, 7 | "tests": [ 8 | { 9 | "description": "all property names valid", 10 | "data": { 11 | "f": {}, 12 | "foo": {} 13 | }, 14 | "valid": true 15 | }, 16 | { 17 | "description": "some property names invalid", 18 | "data": { 19 | "foo": {}, 20 | "foobar": {} 21 | }, 22 | "valid": false 23 | }, 24 | { 25 | "description": "object without properties is valid", 26 | "data": {}, 27 | "valid": true 28 | }, 29 | { 30 | "description": "ignores arrays", 31 | "data": [1, 2, 3, 4], 32 | "valid": true 33 | }, 34 | { 35 | "description": "ignores strings", 36 | "data": "foobar", 37 | "valid": true 38 | }, 39 | { 40 | "description": "ignores other non-objects", 41 | "data": 12, 42 | "valid": true 43 | } 44 | ] 45 | }, 46 | { 47 | "description": "propertyNames with boolean schema true", 48 | "schema": {"propertyNames": true}, 49 | "tests": [ 50 | { 51 | "description": "object with any properties is valid", 52 | "data": {"foo": 1}, 53 | "valid": true 54 | }, 55 | { 56 | "description": "empty object is valid", 57 | "data": {}, 58 | "valid": true 59 | } 60 | ] 61 | }, 62 | { 63 | "description": "propertyNames with boolean schema false", 64 | "schema": {"propertyNames": false}, 65 | "tests": [ 66 | { 67 | "description": "object with any properties is invalid", 68 | "data": {"foo": 1}, 69 | "valid": false 70 | }, 71 | { 72 | "description": "empty object is valid", 73 | "data": {}, 74 | "valid": true 75 | } 76 | ] 77 | } 78 | ] 79 | -------------------------------------------------------------------------------- /testdata/draft2019-09/required.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "required validation", 4 | "schema": { 5 | "properties": { 6 | "foo": {}, 7 | "bar": {} 8 | }, 9 | "required": ["foo"] 10 | }, 11 | "tests": [ 12 | { 13 | "description": "present required property is valid", 14 | "data": {"foo": 1}, 15 | "valid": true 16 | }, 17 | { 18 | "description": "non-present required property is invalid", 19 | "data": {"bar": 1}, 20 | "valid": false 21 | }, 22 | { 23 | "description": "ignores arrays", 24 | "data": [], 25 | "valid": true 26 | }, 27 | { 28 | "description": "ignores strings", 29 | "data": "", 30 | "valid": true 31 | }, 32 | { 33 | "description": "ignores other non-objects", 34 | "data": 12, 35 | "valid": true 36 | } 37 | ] 38 | }, 39 | { 40 | "description": "required default validation", 41 | "schema": { 42 | "properties": { 43 | "foo": {} 44 | } 45 | }, 46 | "tests": [ 47 | { 48 | "description": "not required by default", 49 | "data": {}, 50 | "valid": true 51 | } 52 | ] 53 | }, 54 | { 55 | "description": "required with empty array", 56 | "schema": { 57 | "properties": { 58 | "foo": {} 59 | }, 60 | "required": [] 61 | }, 62 | "tests": [ 63 | { 64 | "description": "property not required", 65 | "data": {}, 66 | "valid": true 67 | } 68 | ] 69 | }, 70 | { 71 | "description": "required with escaped characters", 72 | "schema": { 73 | "required": [ 74 | "foo\nbar", 75 | "foo\"bar", 76 | "foo\\bar", 77 | "foo\rbar", 78 | "foo\tbar", 79 | "foo\fbar" 80 | ] 81 | }, 82 | "tests": [ 83 | { 84 | "description": "object with all properties present is valid", 85 | "data": { 86 | "foo\nbar": 1, 87 | "foo\"bar": 1, 88 | "foo\\bar": 1, 89 | "foo\rbar": 1, 90 | "foo\tbar": 1, 91 | "foo\fbar": 1 92 | }, 93 | "valid": true 94 | }, 95 | { 96 | "description": "object with some properties missing is invalid", 97 | "data": { 98 | "foo\nbar": "1", 99 | "foo\"bar": "1" 100 | }, 101 | "valid": false 102 | } 103 | ] 104 | } 105 | ] 106 | -------------------------------------------------------------------------------- /testdata/draft2019-09/unevaluatedItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "anyOf with false unevaluatedItems", 4 | "schema": { 5 | "$schema": "https://json-schema.org/draft/2019-09/schema", 6 | "unevaluatedItems": false, 7 | "anyOf": [ 8 | {"items": {"type": "string"}}, 9 | {"items": [true, true]} 10 | ] 11 | }, 12 | "tests": [ 13 | { 14 | "description": "all strings is valid", 15 | "data": ["foo", "bar", "baz"], 16 | "valid": true 17 | }, 18 | { 19 | "description": "one item is valid", 20 | "data": [1], 21 | "valid": true 22 | }, 23 | { 24 | "description": "two items are valid", 25 | "data": [1, "two"], 26 | "valid": true 27 | }, 28 | { 29 | "description": "three items are invalid", 30 | "data": [1, "two", "three"], 31 | "valid": false 32 | }, 33 | { 34 | "description": "four strings are valid", 35 | "data": ["one", "two", "three", "four"], 36 | "valid": true 37 | } 38 | ] 39 | }, 40 | { 41 | "description": "complex unevaluated schema", 42 | "schema": { 43 | "$schema": "https://json-schema.org/draft/2019-09/schema", 44 | "unevaluatedItems": { 45 | "allOf": [{"minLength": 3}, {"type": "string"}] 46 | }, 47 | "if": {"items": [{"type": "integer"}, {"type": "array"}]} 48 | }, 49 | "tests": [ 50 | { 51 | "description": "empty array", 52 | "data": [], 53 | "valid": true 54 | }, 55 | { 56 | "description": "if passes with one item", 57 | "data": [1], 58 | "valid": true 59 | }, 60 | { 61 | "description": "if passes with two items", 62 | "data": [1, [2, 3]], 63 | "valid": true 64 | }, 65 | { 66 | "description": "if passes with third valid unevaluated item", 67 | "data": [1, [2, 3], "long-string"], 68 | "valid": true 69 | }, 70 | { 71 | "description": "if passes with third invalid unevaluated item", 72 | "data": [1, [2, 3], "zz"], 73 | "valid": false 74 | }, 75 | { 76 | "description": "if fails with all valid unevaluated items", 77 | "data": ["all", "long", "strings"], 78 | "valid": true 79 | }, 80 | { 81 | "description": "if and unevaluated items fail", 82 | "data": ["a", "b", "c"], 83 | "valid": false 84 | } 85 | ] 86 | } 87 | ] 88 | -------------------------------------------------------------------------------- /testdata/draft2019-09/unevaluatedItems_modified.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "anyOf with false unevaluatedItems", 4 | "schema": { 5 | "$schema": "https://json-schema.org/draft/2019-09/schema", 6 | "unevaluatedItems": false, 7 | "anyOf": [ 8 | {"items": {"type": "string"}}, 9 | {"items": [true, true]} 10 | ] 11 | }, 12 | "tests": [ 13 | { 14 | "description": "all strings is valid", 15 | "data": ["foo", "bar", "baz"], 16 | "valid": true 17 | }, 18 | { 19 | "description": "one item is valid", 20 | "data": [1], 21 | "valid": true 22 | }, 23 | { 24 | "description": "two items are valid", 25 | "data": [1, "two"], 26 | "valid": true 27 | }, 28 | { 29 | "description": "three items are invalid", 30 | "data": [1, "two", "three"], 31 | "valid": false 32 | }, 33 | { 34 | "description": "four strings are valid", 35 | "data": ["one", "two", "three", "four"], 36 | "valid": true 37 | } 38 | ] 39 | }, 40 | { 41 | "description": "complex unevaluated schema", 42 | "schema": { 43 | "$schema": "https://json-schema.org/draft/2019-09/schema", 44 | "unevaluatedItems": { 45 | "allOf": [{"minLength": 3}, {"type": "string"}] 46 | }, 47 | "if": {"items": [{"type": "integer"}, {"type": "array"}]}, 48 | "then": {"items": [{"type": "integer"}, {"type": "array"}]} 49 | }, 50 | "tests": [ 51 | { 52 | "description": "empty array", 53 | "data": [], 54 | "valid": true 55 | }, 56 | { 57 | "description": "if passes with one item", 58 | "data": [1], 59 | "valid": true 60 | }, 61 | { 62 | "description": "if passes with two items", 63 | "data": [1, [2, 3]], 64 | "valid": true 65 | }, 66 | { 67 | "description": "if passes with third valid unevaluated item", 68 | "data": [1, [2, 3], "long-string"], 69 | "valid": true 70 | }, 71 | { 72 | "description": "if passes with third invalid unevaluated item", 73 | "data": [1, [2, 3], "zz"], 74 | "valid": false 75 | }, 76 | { 77 | "description": "if fails with all valid unevaluated items", 78 | "data": ["all", "long", "strings"], 79 | "valid": true 80 | }, 81 | { 82 | "description": "if and unevaluated items fail", 83 | "data": ["a", "b", "c"], 84 | "valid": false 85 | } 86 | ] 87 | } 88 | ] 89 | -------------------------------------------------------------------------------- /testdata/draft2019-09_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "$id": "https://json-schema.org/draft/2019-09/schema", 4 | "$vocabulary": { 5 | "https://json-schema.org/draft/2019-09/vocab/core": true, 6 | "https://json-schema.org/draft/2019-09/vocab/applicator": true, 7 | "https://json-schema.org/draft/2019-09/vocab/validation": true, 8 | "https://json-schema.org/draft/2019-09/vocab/meta-data": true, 9 | "https://json-schema.org/draft/2019-09/vocab/format": false, 10 | "https://json-schema.org/draft/2019-09/vocab/content": true 11 | }, 12 | "$recursiveAnchor": true, 13 | 14 | "title": "Core and Validation specifications meta-schema", 15 | "allOf": [ 16 | {"$ref": "meta/core"}, 17 | {"$ref": "meta/applicator"}, 18 | {"$ref": "meta/validation"}, 19 | {"$ref": "meta/meta-data"}, 20 | {"$ref": "meta/format"}, 21 | {"$ref": "meta/content"} 22 | ], 23 | "type": ["object", "boolean"], 24 | "properties": { 25 | "definitions": { 26 | "$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.", 27 | "type": "object", 28 | "additionalProperties": { "$recursiveRef": "#" }, 29 | "default": {} 30 | }, 31 | "dependencies": { 32 | "$comment": "\"dependencies\" is no longer a keyword, but schema authors should avoid redefining it to facilitate a smooth transition to \"dependentSchemas\" and \"dependentRequired\"", 33 | "type": "object", 34 | "additionalProperties": { 35 | "anyOf": [ 36 | { "$recursiveRef": "#" }, 37 | { "$ref": "meta/validation#/$defs/stringArray" } 38 | ] 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /testdata/draft3/additionalItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "additionalItems as schema", 4 | "schema": { 5 | "items": [], 6 | "additionalItems": {"type": "integer"} 7 | }, 8 | "tests": [ 9 | { 10 | "description": "additional items match schema", 11 | "data": [ 1, 2, 3, 4 ], 12 | "valid": true 13 | }, 14 | { 15 | "description": "additional items do not match schema", 16 | "data": [ 1, 2, 3, "foo" ], 17 | "valid": false 18 | } 19 | ] 20 | }, 21 | { 22 | "description": "items is schema, no additionalItems", 23 | "schema": { 24 | "items": {}, 25 | "additionalItems": false 26 | }, 27 | "tests": [ 28 | { 29 | "description": "all items match schema", 30 | "data": [ 1, 2, 3, 4, 5 ], 31 | "valid": true 32 | } 33 | ] 34 | }, 35 | { 36 | "description": "array of items with no additionalItems", 37 | "schema": { 38 | "items": [{}, {}, {}], 39 | "additionalItems": false 40 | }, 41 | "tests": [ 42 | { 43 | "description": "no additional items present", 44 | "data": [ 1, 2, 3 ], 45 | "valid": true 46 | }, 47 | { 48 | "description": "additional items are not permitted", 49 | "data": [ 1, 2, 3, 4 ], 50 | "valid": false 51 | } 52 | ] 53 | }, 54 | { 55 | "description": "additionalItems as false without items", 56 | "schema": {"additionalItems": false}, 57 | "tests": [ 58 | { 59 | "description": 60 | "items defaults to empty schema so everything is valid", 61 | "data": [ 1, 2, 3, 4, 5 ], 62 | "valid": true 63 | }, 64 | { 65 | "description": "ignores non-arrays", 66 | "data": {"foo" : "bar"}, 67 | "valid": true 68 | } 69 | ] 70 | }, 71 | { 72 | "description": "additionalItems are allowed by default", 73 | "schema": {"items": []}, 74 | "tests": [ 75 | { 76 | "description": "only the first items are validated", 77 | "data": [1, "foo", false], 78 | "valid": true 79 | } 80 | ] 81 | } 82 | ] 83 | -------------------------------------------------------------------------------- /testdata/draft3/default.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "invalid type for default", 4 | "schema": { 5 | "properties": { 6 | "foo": { 7 | "type": "integer", 8 | "default": [] 9 | } 10 | } 11 | }, 12 | "tests": [ 13 | { 14 | "description": "valid when property is specified", 15 | "data": {"foo": 13}, 16 | "valid": true 17 | }, 18 | { 19 | "description": "still valid when the invalid default is used", 20 | "data": {}, 21 | "valid": true 22 | } 23 | ] 24 | }, 25 | { 26 | "description": "invalid string value for default", 27 | "schema": { 28 | "properties": { 29 | "bar": { 30 | "type": "string", 31 | "minLength": 4, 32 | "default": "bad" 33 | } 34 | } 35 | }, 36 | "tests": [ 37 | { 38 | "description": "valid when property is specified", 39 | "data": {"bar": "good"}, 40 | "valid": true 41 | }, 42 | { 43 | "description": "still valid when the invalid default is used", 44 | "data": {}, 45 | "valid": true 46 | } 47 | ] 48 | } 49 | ] 50 | -------------------------------------------------------------------------------- /testdata/draft3/disallow.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "disallow", 4 | "schema": { 5 | "disallow": "integer" 6 | }, 7 | "tests": [ 8 | { 9 | "description": "allowed", 10 | "data": "foo", 11 | "valid": true 12 | }, 13 | { 14 | "description": "disallowed", 15 | "data": 1, 16 | "valid": false 17 | } 18 | ] 19 | }, 20 | { 21 | "description": "multiple disallow", 22 | "schema": { 23 | "disallow": ["integer", "boolean"] 24 | }, 25 | "tests": [ 26 | { 27 | "description": "valid", 28 | "data": "foo", 29 | "valid": true 30 | }, 31 | { 32 | "description": "mismatch", 33 | "data": 1, 34 | "valid": false 35 | }, 36 | { 37 | "description": "other mismatch", 38 | "data": true, 39 | "valid": false 40 | } 41 | ] 42 | }, 43 | { 44 | "description": "multiple disallow subschema", 45 | "schema": { 46 | "disallow": 47 | ["string", 48 | { 49 | "type": "object", 50 | "properties": { 51 | "foo": { 52 | "type": "string" 53 | } 54 | } 55 | }] 56 | }, 57 | "tests": [ 58 | { 59 | "description": "match", 60 | "data": 1, 61 | "valid": true 62 | }, 63 | { 64 | "description": "other match", 65 | "data": {"foo": 1}, 66 | "valid": true 67 | }, 68 | { 69 | "description": "mismatch", 70 | "data": "foo", 71 | "valid": false 72 | }, 73 | { 74 | "description": "other mismatch", 75 | "data": {"foo": "bar"}, 76 | "valid": false 77 | } 78 | ] 79 | } 80 | ] 81 | -------------------------------------------------------------------------------- /testdata/draft3/divisibleBy.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "by int", 4 | "schema": {"divisibleBy": 2}, 5 | "tests": [ 6 | { 7 | "description": "int by int", 8 | "data": 10, 9 | "valid": true 10 | }, 11 | { 12 | "description": "int by int fail", 13 | "data": 7, 14 | "valid": false 15 | }, 16 | { 17 | "description": "ignores non-numbers", 18 | "data": "foo", 19 | "valid": true 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "by number", 25 | "schema": {"divisibleBy": 1.5}, 26 | "tests": [ 27 | { 28 | "description": "zero is divisible by anything (except 0)", 29 | "data": 0, 30 | "valid": true 31 | }, 32 | { 33 | "description": "4.5 is divisible by 1.5", 34 | "data": 4.5, 35 | "valid": true 36 | }, 37 | { 38 | "description": "35 is not divisible by 1.5", 39 | "data": 35, 40 | "valid": false 41 | } 42 | ] 43 | }, 44 | { 45 | "description": "by small number", 46 | "schema": {"divisibleBy": 0.0001}, 47 | "tests": [ 48 | { 49 | "description": "0.0075 is divisible by 0.0001", 50 | "data": 0.0075, 51 | "valid": true 52 | }, 53 | { 54 | "description": "0.00751 is not divisible by 0.0001", 55 | "data": 0.00751, 56 | "valid": false 57 | } 58 | ] 59 | } 60 | ] 61 | -------------------------------------------------------------------------------- /testdata/draft3/enum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "simple enum validation", 4 | "schema": {"enum": [1, 2, 3]}, 5 | "tests": [ 6 | { 7 | "description": "one of the enum is valid", 8 | "data": 1, 9 | "valid": true 10 | }, 11 | { 12 | "description": "something else is invalid", 13 | "data": 4, 14 | "valid": false 15 | } 16 | ] 17 | }, 18 | { 19 | "description": "heterogeneous enum validation", 20 | "schema": {"enum": [6, "foo", [], true, {"foo": 12}]}, 21 | "tests": [ 22 | { 23 | "description": "one of the enum is valid", 24 | "data": [], 25 | "valid": true 26 | }, 27 | { 28 | "description": "something else is invalid", 29 | "data": null, 30 | "valid": false 31 | }, 32 | { 33 | "description": "objects are deep compared", 34 | "data": {"foo": false}, 35 | "valid": false 36 | } 37 | ] 38 | }, 39 | { 40 | "description": "enums in properties", 41 | "schema": { 42 | "type":"object", 43 | "properties": { 44 | "foo": {"enum":["foo"]}, 45 | "bar": {"enum":["bar"], "required":true} 46 | } 47 | }, 48 | "tests": [ 49 | { 50 | "description": "both properties are valid", 51 | "data": {"foo":"foo", "bar":"bar"}, 52 | "valid": true 53 | }, 54 | { 55 | "description": "wrong foo value", 56 | "data": {"foo":"foot", "bar":"bar"}, 57 | "valid": false 58 | }, 59 | { 60 | "description": "wrong bar value", 61 | "data": {"foo":"foo", "bar":"bart"}, 62 | "valid": false 63 | }, 64 | { 65 | "description": "missing optional property is valid", 66 | "data": {"bar":"bar"}, 67 | "valid": true 68 | }, 69 | { 70 | "description": "missing required property is invalid", 71 | "data": {"foo":"foo"}, 72 | "valid": false 73 | }, 74 | { 75 | "description": "missing all properties is invalid", 76 | "data": {}, 77 | "valid": false 78 | } 79 | ] 80 | } 81 | ] 82 | -------------------------------------------------------------------------------- /testdata/draft3/extends.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "extends", 4 | "schema": { 5 | "properties": {"bar": {"type": "integer", "required": true}}, 6 | "extends": { 7 | "properties": { 8 | "foo": {"type": "string", "required": true} 9 | } 10 | } 11 | }, 12 | "tests": [ 13 | { 14 | "description": "extends", 15 | "data": {"foo": "baz", "bar": 2}, 16 | "valid": true 17 | }, 18 | { 19 | "description": "mismatch extends", 20 | "data": {"foo": "baz"}, 21 | "valid": false 22 | }, 23 | { 24 | "description": "mismatch extended", 25 | "data": {"bar": 2}, 26 | "valid": false 27 | }, 28 | { 29 | "description": "wrong type", 30 | "data": {"foo": "baz", "bar": "quux"}, 31 | "valid": false 32 | } 33 | ] 34 | }, 35 | { 36 | "description": "multiple extends", 37 | "schema": { 38 | "properties": {"bar": {"type": "integer", "required": true}}, 39 | "extends" : [ 40 | { 41 | "properties": { 42 | "foo": {"type": "string", "required": true} 43 | } 44 | }, 45 | { 46 | "properties": { 47 | "baz": {"type": "null", "required": true} 48 | } 49 | } 50 | ] 51 | }, 52 | "tests": [ 53 | { 54 | "description": "valid", 55 | "data": {"foo": "quux", "bar": 2, "baz": null}, 56 | "valid": true 57 | }, 58 | { 59 | "description": "mismatch first extends", 60 | "data": {"bar": 2, "baz": null}, 61 | "valid": false 62 | }, 63 | { 64 | "description": "mismatch second extends", 65 | "data": {"foo": "quux", "bar": 2}, 66 | "valid": false 67 | }, 68 | { 69 | "description": "mismatch both", 70 | "data": {"bar": 2}, 71 | "valid": false 72 | } 73 | ] 74 | }, 75 | { 76 | "description": "extends simple types", 77 | "schema": { 78 | "minimum": 20, 79 | "extends": {"maximum": 30} 80 | }, 81 | "tests": [ 82 | { 83 | "description": "valid", 84 | "data": 25, 85 | "valid": true 86 | }, 87 | { 88 | "description": "mismatch extends", 89 | "data": 35, 90 | "valid": false 91 | } 92 | ] 93 | } 94 | ] 95 | -------------------------------------------------------------------------------- /testdata/draft3/items.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "a schema given for items", 4 | "schema": { 5 | "items": {"type": "integer"} 6 | }, 7 | "tests": [ 8 | { 9 | "description": "valid items", 10 | "data": [ 1, 2, 3 ], 11 | "valid": true 12 | }, 13 | { 14 | "description": "wrong type of items", 15 | "data": [1, "x"], 16 | "valid": false 17 | }, 18 | { 19 | "description": "ignores non-arrays", 20 | "data": {"foo" : "bar"}, 21 | "valid": true 22 | } 23 | ] 24 | }, 25 | { 26 | "description": "an array of schemas for items", 27 | "schema": { 28 | "items": [ 29 | {"type": "integer"}, 30 | {"type": "string"} 31 | ] 32 | }, 33 | "tests": [ 34 | { 35 | "description": "correct types", 36 | "data": [ 1, "foo" ], 37 | "valid": true 38 | }, 39 | { 40 | "description": "wrong types", 41 | "data": [ "foo", 1 ], 42 | "valid": false 43 | } 44 | ] 45 | } 46 | ] 47 | -------------------------------------------------------------------------------- /testdata/draft3/maxItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxItems validation", 4 | "schema": {"maxItems": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": [1], 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": [1, 2], 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": [1, 2, 3], 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-arrays", 23 | "data": "foobar", 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /testdata/draft3/maxLength.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxLength validation", 4 | "schema": {"maxLength": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": "f", 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": "fo", 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": "foo", 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-strings", 23 | "data": 10, 24 | "valid": true 25 | }, 26 | { 27 | "description": "two supplementary Unicode code points is long enough", 28 | "data": "\uD83D\uDCA9\uD83D\uDCA9", 29 | "valid": true 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /testdata/draft3/minItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minItems validation", 4 | "schema": {"minItems": 1}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": [1, 2], 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": [1], 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": [], 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-arrays", 23 | "data": "", 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /testdata/draft3/minLength.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minLength validation", 4 | "schema": {"minLength": 2}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": "foo", 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": "fo", 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": "f", 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-strings", 23 | "data": 1, 24 | "valid": true 25 | }, 26 | { 27 | "description": "one supplementary Unicode code point is not long enough", 28 | "data": "\uD83D\uDCA9", 29 | "valid": false 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /testdata/draft3/minimum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minimum validation", 4 | "schema": {"minimum": 1.1}, 5 | "tests": [ 6 | { 7 | "description": "above the minimum is valid", 8 | "data": 2.6, 9 | "valid": true 10 | }, 11 | { 12 | "description": "boundary point is valid", 13 | "data": 1.1, 14 | "valid": true 15 | }, 16 | { 17 | "description": "below the minimum is invalid", 18 | "data": 0.6, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-numbers", 23 | "data": "x", 24 | "valid": true 25 | } 26 | ] 27 | }, 28 | { 29 | "description": "exclusiveMinimum validation", 30 | "schema": { 31 | "minimum": 1.1, 32 | "exclusiveMinimum": true 33 | }, 34 | "tests": [ 35 | { 36 | "description": "above the minimum is still valid", 37 | "data": 1.2, 38 | "valid": true 39 | }, 40 | { 41 | "description": "boundary point is invalid", 42 | "data": 1.1, 43 | "valid": false 44 | } 45 | ] 46 | }, 47 | { 48 | "description": "minimum validation with signed integer", 49 | "schema": {"minimum": -2}, 50 | "tests": [ 51 | { 52 | "description": "negative above the minimum is valid", 53 | "data": -1, 54 | "valid": true 55 | }, 56 | { 57 | "description": "positive above the minimum is valid", 58 | "data": 0, 59 | "valid": true 60 | }, 61 | { 62 | "description": "boundary point is valid", 63 | "data": -2, 64 | "valid": true 65 | }, 66 | { 67 | "description": "boundary point with float is valid", 68 | "data": -2.0, 69 | "valid": true 70 | }, 71 | { 72 | "description": "float below the minimum is invalid", 73 | "data": -2.0001, 74 | "valid": false 75 | }, 76 | { 77 | "description": "int below the minimum is invalid", 78 | "data": -3, 79 | "valid": false 80 | }, 81 | { 82 | "description": "ignores non-numbers", 83 | "data": "x", 84 | "valid": true 85 | } 86 | ] 87 | } 88 | ] 89 | -------------------------------------------------------------------------------- /testdata/draft3/optional/ecmascript-regex.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "ECMA 262 regex dialect recognition", 4 | "schema": { "format": "regex" }, 5 | "tests": [ 6 | { 7 | "description": "[^] is a valid regex", 8 | "data": "[^]", 9 | "valid": true 10 | }, 11 | { 12 | "description": "ECMA 262 has no support for lookbehind", 13 | "data": "(?<=foo)bar", 14 | "valid": false 15 | } 16 | ] 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /testdata/draft3/optional/zeroTerminatedFloats.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "some languages do not distinguish between different types of numeric value", 4 | "schema": { 5 | "type": "integer" 6 | }, 7 | "tests": [ 8 | { 9 | "description": "a float is not an integer even without fractional part", 10 | "data": 1.0, 11 | "valid": false 12 | } 13 | ] 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /testdata/draft3/pattern.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "pattern validation", 4 | "schema": {"pattern": "^a*$"}, 5 | "tests": [ 6 | { 7 | "description": "a matching pattern is valid", 8 | "data": "aaa", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a non-matching pattern is invalid", 13 | "data": "abc", 14 | "valid": false 15 | }, 16 | { 17 | "description": "ignores non-strings", 18 | "data": true, 19 | "valid": true 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "pattern is not anchored", 25 | "schema": {"pattern": "a+"}, 26 | "tests": [ 27 | { 28 | "description": "matches a substring", 29 | "data": "xxaayy", 30 | "valid": true 31 | } 32 | ] 33 | } 34 | ] 35 | -------------------------------------------------------------------------------- /testdata/draft3/refRemote.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "remote ref", 4 | "schema": {"$ref": "http://localhost:1234/integer.json"}, 5 | "tests": [ 6 | { 7 | "description": "remote ref valid", 8 | "data": 1, 9 | "valid": true 10 | }, 11 | { 12 | "description": "remote ref invalid", 13 | "data": "a", 14 | "valid": false 15 | } 16 | ] 17 | }, 18 | { 19 | "description": "fragment within remote ref", 20 | "schema": {"$ref": "http://localhost:1234/subSchemas.json#/integer"}, 21 | "tests": [ 22 | { 23 | "description": "remote fragment valid", 24 | "data": 1, 25 | "valid": true 26 | }, 27 | { 28 | "description": "remote fragment invalid", 29 | "data": "a", 30 | "valid": false 31 | } 32 | ] 33 | }, 34 | { 35 | "description": "ref within remote ref", 36 | "schema": { 37 | "$ref": "http://localhost:1234/subSchemas.json#/refToInteger" 38 | }, 39 | "tests": [ 40 | { 41 | "description": "ref within ref valid", 42 | "data": 1, 43 | "valid": true 44 | }, 45 | { 46 | "description": "ref within ref invalid", 47 | "data": "a", 48 | "valid": false 49 | } 50 | ] 51 | }, 52 | { 53 | "description": "change resolution scope", 54 | "schema": { 55 | "id": "http://localhost:1234/", 56 | "items": { 57 | "id": "folder/", 58 | "items": {"$ref": "folderInteger.json"} 59 | } 60 | }, 61 | "tests": [ 62 | { 63 | "description": "changed scope ref valid", 64 | "data": [[1]], 65 | "valid": true 66 | }, 67 | { 68 | "description": "changed scope ref invalid", 69 | "data": [["a"]], 70 | "valid": false 71 | } 72 | ] 73 | } 74 | ] 75 | -------------------------------------------------------------------------------- /testdata/draft3/required.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "required validation", 4 | "schema": { 5 | "properties": { 6 | "foo": {"required" : true}, 7 | "bar": {} 8 | } 9 | }, 10 | "tests": [ 11 | { 12 | "description": "present required property is valid", 13 | "data": {"foo": 1}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "non-present required property is invalid", 18 | "data": {"bar": 1}, 19 | "valid": false 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "required default validation", 25 | "schema": { 26 | "properties": { 27 | "foo": {} 28 | } 29 | }, 30 | "tests": [ 31 | { 32 | "description": "not required by default", 33 | "data": {}, 34 | "valid": true 35 | } 36 | ] 37 | }, 38 | { 39 | "description": "required explicitly false validation", 40 | "schema": { 41 | "properties": { 42 | "foo": {"required": false} 43 | } 44 | }, 45 | "tests": [ 46 | { 47 | "description": "not required if required is false", 48 | "data": {}, 49 | "valid": true 50 | } 51 | ] 52 | } 53 | ] 54 | -------------------------------------------------------------------------------- /testdata/draft4/additionalItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "additionalItems as schema", 4 | "schema": { 5 | "items": [{}], 6 | "additionalItems": {"type": "integer"} 7 | }, 8 | "tests": [ 9 | { 10 | "description": "additional items match schema", 11 | "data": [ null, 2, 3, 4 ], 12 | "valid": true 13 | }, 14 | { 15 | "description": "additional items do not match schema", 16 | "data": [ null, 2, 3, "foo" ], 17 | "valid": false 18 | } 19 | ] 20 | }, 21 | { 22 | "description": "items is schema, no additionalItems", 23 | "schema": { 24 | "items": {}, 25 | "additionalItems": false 26 | }, 27 | "tests": [ 28 | { 29 | "description": "all items match schema", 30 | "data": [ 1, 2, 3, 4, 5 ], 31 | "valid": true 32 | } 33 | ] 34 | }, 35 | { 36 | "description": "array of items with no additionalItems", 37 | "schema": { 38 | "items": [{}, {}, {}], 39 | "additionalItems": false 40 | }, 41 | "tests": [ 42 | { 43 | "description": "fewer number of items present", 44 | "data": [ 1, 2 ], 45 | "valid": true 46 | }, 47 | { 48 | "description": "equal number of items present", 49 | "data": [ 1, 2, 3 ], 50 | "valid": true 51 | }, 52 | { 53 | "description": "additional items are not permitted", 54 | "data": [ 1, 2, 3, 4 ], 55 | "valid": false 56 | } 57 | ] 58 | }, 59 | { 60 | "description": "additionalItems as false without items", 61 | "schema": {"additionalItems": false}, 62 | "tests": [ 63 | { 64 | "description": 65 | "items defaults to empty schema so everything is valid", 66 | "data": [ 1, 2, 3, 4, 5 ], 67 | "valid": true 68 | }, 69 | { 70 | "description": "ignores non-arrays", 71 | "data": {"foo" : "bar"}, 72 | "valid": true 73 | } 74 | ] 75 | }, 76 | { 77 | "description": "additionalItems are allowed by default", 78 | "schema": {"items": [{"type": "integer"}]}, 79 | "tests": [ 80 | { 81 | "description": "only the first item is validated", 82 | "data": [1, "foo", false], 83 | "valid": true 84 | } 85 | ] 86 | } 87 | ] 88 | -------------------------------------------------------------------------------- /testdata/draft4/default.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "invalid type for default", 4 | "schema": { 5 | "properties": { 6 | "foo": { 7 | "type": "integer", 8 | "default": [] 9 | } 10 | } 11 | }, 12 | "tests": [ 13 | { 14 | "description": "valid when property is specified", 15 | "data": {"foo": 13}, 16 | "valid": true 17 | }, 18 | { 19 | "description": "still valid when the invalid default is used", 20 | "data": {}, 21 | "valid": true 22 | } 23 | ] 24 | }, 25 | { 26 | "description": "invalid string value for default", 27 | "schema": { 28 | "properties": { 29 | "bar": { 30 | "type": "string", 31 | "minLength": 4, 32 | "default": "bad" 33 | } 34 | } 35 | }, 36 | "tests": [ 37 | { 38 | "description": "valid when property is specified", 39 | "data": {"bar": "good"}, 40 | "valid": true 41 | }, 42 | { 43 | "description": "still valid when the invalid default is used", 44 | "data": {}, 45 | "valid": true 46 | } 47 | ] 48 | } 49 | ] 50 | -------------------------------------------------------------------------------- /testdata/draft4/definitions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "valid definition", 4 | "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, 5 | "tests": [ 6 | { 7 | "description": "valid definition schema", 8 | "data": { 9 | "definitions": { 10 | "foo": {"type": "integer"} 11 | } 12 | }, 13 | "valid": true 14 | } 15 | ] 16 | }, 17 | { 18 | "description": "invalid definition", 19 | "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, 20 | "tests": [ 21 | { 22 | "description": "invalid definition schema", 23 | "data": { 24 | "definitions": { 25 | "foo": {"type": 1} 26 | } 27 | }, 28 | "valid": false 29 | } 30 | ] 31 | } 32 | ] 33 | -------------------------------------------------------------------------------- /testdata/draft4/maxItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxItems validation", 4 | "schema": {"maxItems": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": [1], 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": [1, 2], 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": [1, 2, 3], 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-arrays", 23 | "data": "foobar", 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /testdata/draft4/maxLength.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxLength validation", 4 | "schema": {"maxLength": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": "f", 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": "fo", 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": "foo", 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-strings", 23 | "data": 100, 24 | "valid": true 25 | }, 26 | { 27 | "description": "two supplementary Unicode code points is long enough", 28 | "data": "\uD83D\uDCA9\uD83D\uDCA9", 29 | "valid": true 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /testdata/draft4/maxProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxProperties validation", 4 | "schema": {"maxProperties": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": {"foo": 1}, 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": {"foo": 1, "bar": 2}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": {"foo": 1, "bar": 2, "baz": 3}, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores arrays", 23 | "data": [1, 2, 3], 24 | "valid": true 25 | }, 26 | { 27 | "description": "ignores strings", 28 | "data": "foobar", 29 | "valid": true 30 | }, 31 | { 32 | "description": "ignores other non-objects", 33 | "data": 12, 34 | "valid": true 35 | } 36 | ] 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /testdata/draft4/minItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minItems validation", 4 | "schema": {"minItems": 1}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": [1, 2], 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": [1], 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": [], 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-arrays", 23 | "data": "", 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /testdata/draft4/minLength.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minLength validation", 4 | "schema": {"minLength": 2}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": "foo", 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": "fo", 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": "f", 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-strings", 23 | "data": 1, 24 | "valid": true 25 | }, 26 | { 27 | "description": "one supplementary Unicode code point is not long enough", 28 | "data": "\uD83D\uDCA9", 29 | "valid": false 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /testdata/draft4/minProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minProperties validation", 4 | "schema": {"minProperties": 1}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": {"foo": 1, "bar": 2}, 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": {"foo": 1}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": {}, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores arrays", 23 | "data": [], 24 | "valid": true 25 | }, 26 | { 27 | "description": "ignores strings", 28 | "data": "", 29 | "valid": true 30 | }, 31 | { 32 | "description": "ignores other non-objects", 33 | "data": 12, 34 | "valid": true 35 | } 36 | ] 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /testdata/draft4/multipleOf.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "by int", 4 | "schema": {"multipleOf": 2}, 5 | "tests": [ 6 | { 7 | "description": "int by int", 8 | "data": 10, 9 | "valid": true 10 | }, 11 | { 12 | "description": "int by int fail", 13 | "data": 7, 14 | "valid": false 15 | }, 16 | { 17 | "description": "ignores non-numbers", 18 | "data": "foo", 19 | "valid": true 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "by number", 25 | "schema": {"multipleOf": 1.5}, 26 | "tests": [ 27 | { 28 | "description": "zero is multiple of anything", 29 | "data": 0, 30 | "valid": true 31 | }, 32 | { 33 | "description": "4.5 is multiple of 1.5", 34 | "data": 4.5, 35 | "valid": true 36 | }, 37 | { 38 | "description": "35 is not multiple of 1.5", 39 | "data": 35, 40 | "valid": false 41 | } 42 | ] 43 | }, 44 | { 45 | "description": "by small number", 46 | "schema": {"multipleOf": 0.0001}, 47 | "tests": [ 48 | { 49 | "description": "0.0075 is multiple of 0.0001", 50 | "data": 0.0075, 51 | "valid": true 52 | }, 53 | { 54 | "description": "0.00751 is not multiple of 0.0001", 55 | "data": 0.00751, 56 | "valid": false 57 | } 58 | ] 59 | } 60 | ] 61 | -------------------------------------------------------------------------------- /testdata/draft4/not.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "not", 4 | "schema": { 5 | "not": {"type": "integer"} 6 | }, 7 | "tests": [ 8 | { 9 | "description": "allowed", 10 | "data": "foo", 11 | "valid": true 12 | }, 13 | { 14 | "description": "disallowed", 15 | "data": 1, 16 | "valid": false 17 | } 18 | ] 19 | }, 20 | { 21 | "description": "not multiple types", 22 | "schema": { 23 | "not": {"type": ["integer", "boolean"]} 24 | }, 25 | "tests": [ 26 | { 27 | "description": "valid", 28 | "data": "foo", 29 | "valid": true 30 | }, 31 | { 32 | "description": "mismatch", 33 | "data": 1, 34 | "valid": false 35 | }, 36 | { 37 | "description": "other mismatch", 38 | "data": true, 39 | "valid": false 40 | } 41 | ] 42 | }, 43 | { 44 | "description": "not more complex schema", 45 | "schema": { 46 | "not": { 47 | "type": "object", 48 | "properties": { 49 | "foo": { 50 | "type": "string" 51 | } 52 | } 53 | } 54 | }, 55 | "tests": [ 56 | { 57 | "description": "match", 58 | "data": 1, 59 | "valid": true 60 | }, 61 | { 62 | "description": "other match", 63 | "data": {"foo": 1}, 64 | "valid": true 65 | }, 66 | { 67 | "description": "mismatch", 68 | "data": {"foo": "bar"}, 69 | "valid": false 70 | } 71 | ] 72 | }, 73 | { 74 | "description": "forbidden property", 75 | "schema": { 76 | "properties": { 77 | "foo": { 78 | "not": {} 79 | } 80 | } 81 | }, 82 | "tests": [ 83 | { 84 | "description": "property present", 85 | "data": {"foo": 1, "bar": 2}, 86 | "valid": false 87 | }, 88 | { 89 | "description": "property absent", 90 | "data": {"bar": 1, "baz": 2}, 91 | "valid": true 92 | } 93 | ] 94 | } 95 | 96 | ] 97 | -------------------------------------------------------------------------------- /testdata/draft4/optional/zeroTerminatedFloats.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "some languages do not distinguish between different types of numeric value", 4 | "schema": { 5 | "type": "integer" 6 | }, 7 | "tests": [ 8 | { 9 | "description": "a float is not an integer even without fractional part", 10 | "data": 1.0, 11 | "valid": false 12 | } 13 | ] 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /testdata/draft4/pattern.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "pattern validation", 4 | "schema": {"pattern": "^a*$"}, 5 | "tests": [ 6 | { 7 | "description": "a matching pattern is valid", 8 | "data": "aaa", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a non-matching pattern is invalid", 13 | "data": "abc", 14 | "valid": false 15 | }, 16 | { 17 | "description": "ignores non-strings", 18 | "data": true, 19 | "valid": true 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "pattern is not anchored", 25 | "schema": {"pattern": "a+"}, 26 | "tests": [ 27 | { 28 | "description": "matches a substring", 29 | "data": "xxaayy", 30 | "valid": true 31 | } 32 | ] 33 | } 34 | ] 35 | -------------------------------------------------------------------------------- /testdata/draft4/required.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "required validation", 4 | "schema": { 5 | "properties": { 6 | "foo": {}, 7 | "bar": {} 8 | }, 9 | "required": ["foo"] 10 | }, 11 | "tests": [ 12 | { 13 | "description": "present required property is valid", 14 | "data": {"foo": 1}, 15 | "valid": true 16 | }, 17 | { 18 | "description": "non-present required property is invalid", 19 | "data": {"bar": 1}, 20 | "valid": false 21 | }, 22 | { 23 | "description": "ignores arrays", 24 | "data": [], 25 | "valid": true 26 | }, 27 | { 28 | "description": "ignores strings", 29 | "data": "", 30 | "valid": true 31 | }, 32 | { 33 | "description": "ignores other non-objects", 34 | "data": 12, 35 | "valid": true 36 | } 37 | ] 38 | }, 39 | { 40 | "description": "required default validation", 41 | "schema": { 42 | "properties": { 43 | "foo": {} 44 | } 45 | }, 46 | "tests": [ 47 | { 48 | "description": "not required by default", 49 | "data": {}, 50 | "valid": true 51 | } 52 | ] 53 | }, 54 | { 55 | "description": "required with escaped characters", 56 | "schema": { 57 | "required": [ 58 | "foo\nbar", 59 | "foo\"bar", 60 | "foo\\bar", 61 | "foo\rbar", 62 | "foo\tbar", 63 | "foo\fbar" 64 | ] 65 | }, 66 | "tests": [ 67 | { 68 | "description": "object with all properties present is valid", 69 | "data": { 70 | "foo\nbar": 1, 71 | "foo\"bar": 1, 72 | "foo\\bar": 1, 73 | "foo\rbar": 1, 74 | "foo\tbar": 1, 75 | "foo\fbar": 1 76 | }, 77 | "valid": true 78 | }, 79 | { 80 | "description": "object with some properties missing is invalid", 81 | "data": { 82 | "foo\nbar": "1", 83 | "foo\"bar": "1" 84 | }, 85 | "valid": false 86 | } 87 | ] 88 | } 89 | ] 90 | -------------------------------------------------------------------------------- /testdata/draft6/additionalItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "additionalItems as schema", 4 | "schema": { 5 | "items": [{}], 6 | "additionalItems": {"type": "integer"} 7 | }, 8 | "tests": [ 9 | { 10 | "description": "additional items match schema", 11 | "data": [ null, 2, 3, 4 ], 12 | "valid": true 13 | }, 14 | { 15 | "description": "additional items do not match schema", 16 | "data": [ null, 2, 3, "foo" ], 17 | "valid": false 18 | } 19 | ] 20 | }, 21 | { 22 | "description": "items is schema, no additionalItems", 23 | "schema": { 24 | "items": {}, 25 | "additionalItems": false 26 | }, 27 | "tests": [ 28 | { 29 | "description": "all items match schema", 30 | "data": [ 1, 2, 3, 4, 5 ], 31 | "valid": true 32 | } 33 | ] 34 | }, 35 | { 36 | "description": "array of items with no additionalItems", 37 | "schema": { 38 | "items": [{}, {}, {}], 39 | "additionalItems": false 40 | }, 41 | "tests": [ 42 | { 43 | "description": "fewer number of items present", 44 | "data": [ 1, 2 ], 45 | "valid": true 46 | }, 47 | { 48 | "description": "equal number of items present", 49 | "data": [ 1, 2, 3 ], 50 | "valid": true 51 | }, 52 | { 53 | "description": "additional items are not permitted", 54 | "data": [ 1, 2, 3, 4 ], 55 | "valid": false 56 | } 57 | ] 58 | }, 59 | { 60 | "description": "additionalItems as false without items", 61 | "schema": {"additionalItems": false}, 62 | "tests": [ 63 | { 64 | "description": 65 | "items defaults to empty schema so everything is valid", 66 | "data": [ 1, 2, 3, 4, 5 ], 67 | "valid": true 68 | }, 69 | { 70 | "description": "ignores non-arrays", 71 | "data": {"foo" : "bar"}, 72 | "valid": true 73 | } 74 | ] 75 | }, 76 | { 77 | "description": "additionalItems are allowed by default", 78 | "schema": {"items": [{"type": "integer"}]}, 79 | "tests": [ 80 | { 81 | "description": "only the first item is validated", 82 | "data": [1, "foo", false], 83 | "valid": true 84 | } 85 | ] 86 | } 87 | ] 88 | -------------------------------------------------------------------------------- /testdata/draft6/default.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "invalid type for default", 4 | "schema": { 5 | "properties": { 6 | "foo": { 7 | "type": "integer", 8 | "default": [] 9 | } 10 | } 11 | }, 12 | "tests": [ 13 | { 14 | "description": "valid when property is specified", 15 | "data": {"foo": 13}, 16 | "valid": true 17 | }, 18 | { 19 | "description": "still valid when the invalid default is used", 20 | "data": {}, 21 | "valid": true 22 | } 23 | ] 24 | }, 25 | { 26 | "description": "invalid string value for default", 27 | "schema": { 28 | "properties": { 29 | "bar": { 30 | "type": "string", 31 | "minLength": 4, 32 | "default": "bad" 33 | } 34 | } 35 | }, 36 | "tests": [ 37 | { 38 | "description": "valid when property is specified", 39 | "data": {"bar": "good"}, 40 | "valid": true 41 | }, 42 | { 43 | "description": "still valid when the invalid default is used", 44 | "data": {}, 45 | "valid": true 46 | } 47 | ] 48 | } 49 | ] 50 | -------------------------------------------------------------------------------- /testdata/draft6/definitions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "valid definition", 4 | "schema": {"$ref": "http://json-schema.org/draft-06/schema#"}, 5 | "tests": [ 6 | { 7 | "description": "valid definition schema", 8 | "data": { 9 | "definitions": { 10 | "foo": {"type": "integer"} 11 | } 12 | }, 13 | "valid": true 14 | } 15 | ] 16 | }, 17 | { 18 | "description": "invalid definition", 19 | "schema": {"$ref": "http://json-schema.org/draft-06/schema#"}, 20 | "tests": [ 21 | { 22 | "description": "invalid definition schema", 23 | "data": { 24 | "definitions": { 25 | "foo": {"type": 1} 26 | } 27 | }, 28 | "valid": false 29 | } 30 | ] 31 | } 32 | ] 33 | -------------------------------------------------------------------------------- /testdata/draft6/exclusiveMaximum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "exclusiveMaximum validation", 4 | "schema": { 5 | "exclusiveMaximum": 3.0 6 | }, 7 | "tests": [ 8 | { 9 | "description": "below the exclusiveMaximum is valid", 10 | "data": 2.2, 11 | "valid": true 12 | }, 13 | { 14 | "description": "boundary point is invalid", 15 | "data": 3.0, 16 | "valid": false 17 | }, 18 | { 19 | "description": "above the exclusiveMaximum is invalid", 20 | "data": 3.5, 21 | "valid": false 22 | }, 23 | { 24 | "description": "ignores non-numbers", 25 | "data": "x", 26 | "valid": true 27 | } 28 | ] 29 | } 30 | ] 31 | -------------------------------------------------------------------------------- /testdata/draft6/exclusiveMinimum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "exclusiveMinimum validation", 4 | "schema": { 5 | "exclusiveMinimum": 1.1 6 | }, 7 | "tests": [ 8 | { 9 | "description": "above the exclusiveMinimum is valid", 10 | "data": 1.2, 11 | "valid": true 12 | }, 13 | { 14 | "description": "boundary point is invalid", 15 | "data": 1.1, 16 | "valid": false 17 | }, 18 | { 19 | "description": "below the exclusiveMinimum is invalid", 20 | "data": 0.6, 21 | "valid": false 22 | }, 23 | { 24 | "description": "ignores non-numbers", 25 | "data": "x", 26 | "valid": true 27 | } 28 | ] 29 | } 30 | ] 31 | -------------------------------------------------------------------------------- /testdata/draft6/maxItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxItems validation", 4 | "schema": {"maxItems": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": [1], 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": [1, 2], 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": [1, 2, 3], 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-arrays", 23 | "data": "foobar", 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /testdata/draft6/maxLength.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxLength validation", 4 | "schema": {"maxLength": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": "f", 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": "fo", 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": "foo", 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-strings", 23 | "data": 100, 24 | "valid": true 25 | }, 26 | { 27 | "description": "two supplementary Unicode code points is long enough", 28 | "data": "\uD83D\uDCA9\uD83D\uDCA9", 29 | "valid": true 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /testdata/draft6/maxProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxProperties validation", 4 | "schema": {"maxProperties": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": {"foo": 1}, 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": {"foo": 1, "bar": 2}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": {"foo": 1, "bar": 2, "baz": 3}, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores arrays", 23 | "data": [1, 2, 3], 24 | "valid": true 25 | }, 26 | { 27 | "description": "ignores strings", 28 | "data": "foobar", 29 | "valid": true 30 | }, 31 | { 32 | "description": "ignores other non-objects", 33 | "data": 12, 34 | "valid": true 35 | } 36 | ] 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /testdata/draft6/maximum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maximum validation", 4 | "schema": {"maximum": 3.0}, 5 | "tests": [ 6 | { 7 | "description": "below the maximum is valid", 8 | "data": 2.6, 9 | "valid": true 10 | }, 11 | { 12 | "description": "boundary point is valid", 13 | "data": 3.0, 14 | "valid": true 15 | }, 16 | { 17 | "description": "above the maximum is invalid", 18 | "data": 3.5, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-numbers", 23 | "data": "x", 24 | "valid": true 25 | } 26 | ] 27 | }, 28 | { 29 | "description": "maximum validation with unsigned integer", 30 | "schema": {"maximum": 300}, 31 | "tests": [ 32 | { 33 | "description": "below the maximum is invalid", 34 | "data": 299.97, 35 | "valid": true 36 | }, 37 | { 38 | "description": "boundary point integer is valid", 39 | "data": 300, 40 | "valid": true 41 | }, 42 | { 43 | "description": "boundary point float is valid", 44 | "data": 300.00, 45 | "valid": true 46 | }, 47 | { 48 | "description": "above the maximum is invalid", 49 | "data": 300.5, 50 | "valid": false 51 | } 52 | ] 53 | } 54 | ] 55 | -------------------------------------------------------------------------------- /testdata/draft6/minItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minItems validation", 4 | "schema": {"minItems": 1}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": [1, 2], 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": [1], 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": [], 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-arrays", 23 | "data": "", 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /testdata/draft6/minLength.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minLength validation", 4 | "schema": {"minLength": 2}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": "foo", 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": "fo", 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": "f", 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-strings", 23 | "data": 1, 24 | "valid": true 25 | }, 26 | { 27 | "description": "one supplementary Unicode code point is not long enough", 28 | "data": "\uD83D\uDCA9", 29 | "valid": false 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /testdata/draft6/minProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minProperties validation", 4 | "schema": {"minProperties": 1}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": {"foo": 1, "bar": 2}, 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": {"foo": 1}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": {}, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores arrays", 23 | "data": [], 24 | "valid": true 25 | }, 26 | { 27 | "description": "ignores strings", 28 | "data": "", 29 | "valid": true 30 | }, 31 | { 32 | "description": "ignores other non-objects", 33 | "data": 12, 34 | "valid": true 35 | } 36 | ] 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /testdata/draft6/minimum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minimum validation", 4 | "schema": {"minimum": 1.1}, 5 | "tests": [ 6 | { 7 | "description": "above the minimum is valid", 8 | "data": 2.6, 9 | "valid": true 10 | }, 11 | { 12 | "description": "boundary point is valid", 13 | "data": 1.1, 14 | "valid": true 15 | }, 16 | { 17 | "description": "below the minimum is invalid", 18 | "data": 0.6, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-numbers", 23 | "data": "x", 24 | "valid": true 25 | } 26 | ] 27 | }, 28 | { 29 | "description": "minimum validation with signed integer", 30 | "schema": {"minimum": -2}, 31 | "tests": [ 32 | { 33 | "description": "negative above the minimum is valid", 34 | "data": -1, 35 | "valid": true 36 | }, 37 | { 38 | "description": "positive above the minimum is valid", 39 | "data": 0, 40 | "valid": true 41 | }, 42 | { 43 | "description": "boundary point is valid", 44 | "data": -2, 45 | "valid": true 46 | }, 47 | { 48 | "description": "boundary point with float is valid", 49 | "data": -2.0, 50 | "valid": true 51 | }, 52 | { 53 | "description": "float below the minimum is invalid", 54 | "data": -2.0001, 55 | "valid": false 56 | }, 57 | { 58 | "description": "int below the minimum is invalid", 59 | "data": -3, 60 | "valid": false 61 | }, 62 | { 63 | "description": "ignores non-numbers", 64 | "data": "x", 65 | "valid": true 66 | } 67 | ] 68 | } 69 | ] 70 | -------------------------------------------------------------------------------- /testdata/draft6/multipleOf.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "by int", 4 | "schema": {"multipleOf": 2}, 5 | "tests": [ 6 | { 7 | "description": "int by int", 8 | "data": 10, 9 | "valid": true 10 | }, 11 | { 12 | "description": "int by int fail", 13 | "data": 7, 14 | "valid": false 15 | }, 16 | { 17 | "description": "ignores non-numbers", 18 | "data": "foo", 19 | "valid": true 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "by number", 25 | "schema": {"multipleOf": 1.5}, 26 | "tests": [ 27 | { 28 | "description": "zero is multiple of anything", 29 | "data": 0, 30 | "valid": true 31 | }, 32 | { 33 | "description": "4.5 is multiple of 1.5", 34 | "data": 4.5, 35 | "valid": true 36 | }, 37 | { 38 | "description": "35 is not multiple of 1.5", 39 | "data": 35, 40 | "valid": false 41 | } 42 | ] 43 | }, 44 | { 45 | "description": "by small number", 46 | "schema": {"multipleOf": 0.0001}, 47 | "tests": [ 48 | { 49 | "description": "0.0075 is multiple of 0.0001", 50 | "data": 0.0075, 51 | "valid": true 52 | }, 53 | { 54 | "description": "0.00751 is not multiple of 0.0001", 55 | "data": 0.00751, 56 | "valid": false 57 | } 58 | ] 59 | } 60 | ] 61 | -------------------------------------------------------------------------------- /testdata/draft6/optional/zeroTerminatedFloats.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "some languages do not distinguish between different types of numeric value", 4 | "schema": { 5 | "type": "integer" 6 | }, 7 | "tests": [ 8 | { 9 | "description": "a float without fractional part is an integer", 10 | "data": 1.0, 11 | "valid": true 12 | } 13 | ] 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /testdata/draft6/pattern.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "pattern validation", 4 | "schema": {"pattern": "^a*$"}, 5 | "tests": [ 6 | { 7 | "description": "a matching pattern is valid", 8 | "data": "aaa", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a non-matching pattern is invalid", 13 | "data": "abc", 14 | "valid": false 15 | }, 16 | { 17 | "description": "ignores non-strings", 18 | "data": true, 19 | "valid": true 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "pattern is not anchored", 25 | "schema": {"pattern": "a+"}, 26 | "tests": [ 27 | { 28 | "description": "matches a substring", 29 | "data": "xxaayy", 30 | "valid": true 31 | } 32 | ] 33 | } 34 | ] 35 | -------------------------------------------------------------------------------- /testdata/draft6/propertyNames.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "propertyNames validation", 4 | "schema": { 5 | "propertyNames": {"maxLength": 3} 6 | }, 7 | "tests": [ 8 | { 9 | "description": "all property names valid", 10 | "data": { 11 | "f": {}, 12 | "foo": {} 13 | }, 14 | "valid": true 15 | }, 16 | { 17 | "description": "some property names invalid", 18 | "data": { 19 | "foo": {}, 20 | "foobar": {} 21 | }, 22 | "valid": false 23 | }, 24 | { 25 | "description": "object without properties is valid", 26 | "data": {}, 27 | "valid": true 28 | }, 29 | { 30 | "description": "ignores arrays", 31 | "data": [1, 2, 3, 4], 32 | "valid": true 33 | }, 34 | { 35 | "description": "ignores strings", 36 | "data": "foobar", 37 | "valid": true 38 | }, 39 | { 40 | "description": "ignores other non-objects", 41 | "data": 12, 42 | "valid": true 43 | } 44 | ] 45 | }, 46 | { 47 | "description": "propertyNames with boolean schema true", 48 | "schema": {"propertyNames": true}, 49 | "tests": [ 50 | { 51 | "description": "object with any properties is valid", 52 | "data": {"foo": 1}, 53 | "valid": true 54 | }, 55 | { 56 | "description": "empty object is valid", 57 | "data": {}, 58 | "valid": true 59 | } 60 | ] 61 | }, 62 | { 63 | "description": "propertyNames with boolean schema false", 64 | "schema": {"propertyNames": false}, 65 | "tests": [ 66 | { 67 | "description": "object with any properties is invalid", 68 | "data": {"foo": 1}, 69 | "valid": false 70 | }, 71 | { 72 | "description": "empty object is valid", 73 | "data": {}, 74 | "valid": true 75 | } 76 | ] 77 | } 78 | ] 79 | -------------------------------------------------------------------------------- /testdata/draft6/required.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "required validation", 4 | "schema": { 5 | "properties": { 6 | "foo": {}, 7 | "bar": {} 8 | }, 9 | "required": ["foo"] 10 | }, 11 | "tests": [ 12 | { 13 | "description": "present required property is valid", 14 | "data": {"foo": 1}, 15 | "valid": true 16 | }, 17 | { 18 | "description": "non-present required property is invalid", 19 | "data": {"bar": 1}, 20 | "valid": false 21 | }, 22 | { 23 | "description": "ignores arrays", 24 | "data": [], 25 | "valid": true 26 | }, 27 | { 28 | "description": "ignores strings", 29 | "data": "", 30 | "valid": true 31 | }, 32 | { 33 | "description": "ignores other non-objects", 34 | "data": 12, 35 | "valid": true 36 | } 37 | ] 38 | }, 39 | { 40 | "description": "required default validation", 41 | "schema": { 42 | "properties": { 43 | "foo": {} 44 | } 45 | }, 46 | "tests": [ 47 | { 48 | "description": "not required by default", 49 | "data": {}, 50 | "valid": true 51 | } 52 | ] 53 | }, 54 | { 55 | "description": "required with empty array", 56 | "schema": { 57 | "properties": { 58 | "foo": {} 59 | }, 60 | "required": [] 61 | }, 62 | "tests": [ 63 | { 64 | "description": "property not required", 65 | "data": {}, 66 | "valid": true 67 | } 68 | ] 69 | }, 70 | { 71 | "description": "required with escaped characters", 72 | "schema": { 73 | "required": [ 74 | "foo\nbar", 75 | "foo\"bar", 76 | "foo\\bar", 77 | "foo\rbar", 78 | "foo\tbar", 79 | "foo\fbar" 80 | ] 81 | }, 82 | "tests": [ 83 | { 84 | "description": "object with all properties present is valid", 85 | "data": { 86 | "foo\nbar": 1, 87 | "foo\"bar": 1, 88 | "foo\\bar": 1, 89 | "foo\rbar": 1, 90 | "foo\tbar": 1, 91 | "foo\fbar": 1 92 | }, 93 | "valid": true 94 | }, 95 | { 96 | "description": "object with some properties missing is invalid", 97 | "data": { 98 | "foo\nbar": "1", 99 | "foo\"bar": "1" 100 | }, 101 | "valid": false 102 | } 103 | ] 104 | } 105 | ] 106 | -------------------------------------------------------------------------------- /testdata/draft7/additionalItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "additionalItems as schema", 4 | "schema": { 5 | "items": [{}], 6 | "additionalItems": {"type": "integer"} 7 | }, 8 | "tests": [ 9 | { 10 | "description": "additional items match schema", 11 | "data": [ null, 2, 3, 4 ], 12 | "valid": true 13 | }, 14 | { 15 | "description": "additional items do not match schema", 16 | "data": [ null, 2, 3, "foo" ], 17 | "valid": false 18 | } 19 | ] 20 | }, 21 | { 22 | "description": "items is schema, no additionalItems", 23 | "schema": { 24 | "items": {}, 25 | "additionalItems": false 26 | }, 27 | "tests": [ 28 | { 29 | "description": "all items match schema", 30 | "data": [ 1, 2, 3, 4, 5 ], 31 | "valid": true 32 | } 33 | ] 34 | }, 35 | { 36 | "description": "array of items with no additionalItems", 37 | "schema": { 38 | "items": [{}, {}, {}], 39 | "additionalItems": false 40 | }, 41 | "tests": [ 42 | { 43 | "description": "fewer number of items present", 44 | "data": [ 1, 2 ], 45 | "valid": true 46 | }, 47 | { 48 | "description": "equal number of items present", 49 | "data": [ 1, 2, 3 ], 50 | "valid": true 51 | }, 52 | { 53 | "description": "additional items are not permitted", 54 | "data": [ 1, 2, 3, 4 ], 55 | "valid": false 56 | } 57 | ] 58 | }, 59 | { 60 | "description": "additionalItems as false without items", 61 | "schema": {"additionalItems": false}, 62 | "tests": [ 63 | { 64 | "description": 65 | "items defaults to empty schema so everything is valid", 66 | "data": [ 1, 2, 3, 4, 5 ], 67 | "valid": true 68 | }, 69 | { 70 | "description": "ignores non-arrays", 71 | "data": {"foo" : "bar"}, 72 | "valid": true 73 | } 74 | ] 75 | }, 76 | { 77 | "description": "additionalItems are allowed by default", 78 | "schema": {"items": [{"type": "integer"}]}, 79 | "tests": [ 80 | { 81 | "description": "only the first item is validated", 82 | "data": [1, "foo", false], 83 | "valid": true 84 | } 85 | ] 86 | } 87 | ] 88 | -------------------------------------------------------------------------------- /testdata/draft7/default.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "invalid type for default", 4 | "schema": { 5 | "properties": { 6 | "foo": { 7 | "type": "integer", 8 | "default": [] 9 | } 10 | } 11 | }, 12 | "tests": [ 13 | { 14 | "description": "valid when property is specified", 15 | "data": {"foo": 13}, 16 | "valid": true 17 | }, 18 | { 19 | "description": "still valid when the invalid default is used", 20 | "data": {}, 21 | "valid": true 22 | } 23 | ] 24 | }, 25 | { 26 | "description": "invalid string value for default", 27 | "schema": { 28 | "properties": { 29 | "bar": { 30 | "type": "string", 31 | "minLength": 4, 32 | "default": "bad" 33 | } 34 | } 35 | }, 36 | "tests": [ 37 | { 38 | "description": "valid when property is specified", 39 | "data": {"bar": "good"}, 40 | "valid": true 41 | }, 42 | { 43 | "description": "still valid when the invalid default is used", 44 | "data": {}, 45 | "valid": true 46 | } 47 | ] 48 | } 49 | ] 50 | -------------------------------------------------------------------------------- /testdata/draft7/definitions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "valid definition", 4 | "schema": {"$ref": "http://json-schema.org/draft-07/schema#"}, 5 | "tests": [ 6 | { 7 | "description": "valid definition schema", 8 | "data": { 9 | "definitions": { 10 | "foo": {"type": "integer"} 11 | } 12 | }, 13 | "valid": true 14 | } 15 | ] 16 | }, 17 | { 18 | "description": "invalid definition", 19 | "schema": {"$ref": "http://json-schema.org/draft-07/schema#"}, 20 | "tests": [ 21 | { 22 | "description": "invalid definition schema", 23 | "data": { 24 | "definitions": { 25 | "foo": {"type": 1} 26 | } 27 | }, 28 | "valid": false 29 | } 30 | ] 31 | } 32 | ] 33 | -------------------------------------------------------------------------------- /testdata/draft7/exclusiveMaximum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "exclusiveMaximum validation", 4 | "schema": { 5 | "exclusiveMaximum": 3.0 6 | }, 7 | "tests": [ 8 | { 9 | "description": "below the exclusiveMaximum is valid", 10 | "data": 2.2, 11 | "valid": true 12 | }, 13 | { 14 | "description": "boundary point is invalid", 15 | "data": 3.0, 16 | "valid": false 17 | }, 18 | { 19 | "description": "above the exclusiveMaximum is invalid", 20 | "data": 3.5, 21 | "valid": false 22 | }, 23 | { 24 | "description": "ignores non-numbers", 25 | "data": "x", 26 | "valid": true 27 | } 28 | ] 29 | } 30 | ] 31 | -------------------------------------------------------------------------------- /testdata/draft7/exclusiveMinimum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "exclusiveMinimum validation", 4 | "schema": { 5 | "exclusiveMinimum": 1.1 6 | }, 7 | "tests": [ 8 | { 9 | "description": "above the exclusiveMinimum is valid", 10 | "data": 1.2, 11 | "valid": true 12 | }, 13 | { 14 | "description": "boundary point is invalid", 15 | "data": 1.1, 16 | "valid": false 17 | }, 18 | { 19 | "description": "below the exclusiveMinimum is invalid", 20 | "data": 0.6, 21 | "valid": false 22 | }, 23 | { 24 | "description": "ignores non-numbers", 25 | "data": "x", 26 | "valid": true 27 | } 28 | ] 29 | } 30 | ] 31 | -------------------------------------------------------------------------------- /testdata/draft7/maxItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxItems validation", 4 | "schema": {"maxItems": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": [1], 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": [1, 2], 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": [1, 2, 3], 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-arrays", 23 | "data": "foobar", 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /testdata/draft7/maxLength.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxLength validation", 4 | "schema": {"maxLength": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": "f", 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": "fo", 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": "foo", 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-strings", 23 | "data": 100, 24 | "valid": true 25 | }, 26 | { 27 | "description": "two supplementary Unicode code points is long enough", 28 | "data": "\uD83D\uDCA9\uD83D\uDCA9", 29 | "valid": true 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /testdata/draft7/maxProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxProperties validation", 4 | "schema": {"maxProperties": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": {"foo": 1}, 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": {"foo": 1, "bar": 2}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": {"foo": 1, "bar": 2, "baz": 3}, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores arrays", 23 | "data": [1, 2, 3], 24 | "valid": true 25 | }, 26 | { 27 | "description": "ignores strings", 28 | "data": "foobar", 29 | "valid": true 30 | }, 31 | { 32 | "description": "ignores other non-objects", 33 | "data": 12, 34 | "valid": true 35 | } 36 | ] 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /testdata/draft7/maximum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maximum validation", 4 | "schema": {"maximum": 3.0}, 5 | "tests": [ 6 | { 7 | "description": "below the maximum is valid", 8 | "data": 2.6, 9 | "valid": true 10 | }, 11 | { 12 | "description": "boundary point is valid", 13 | "data": 3.0, 14 | "valid": true 15 | }, 16 | { 17 | "description": "above the maximum is invalid", 18 | "data": 3.5, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-numbers", 23 | "data": "x", 24 | "valid": true 25 | } 26 | ] 27 | }, 28 | { 29 | "description": "maximum validation with unsigned integer", 30 | "schema": {"maximum": 300}, 31 | "tests": [ 32 | { 33 | "description": "below the maximum is invalid", 34 | "data": 299.97, 35 | "valid": true 36 | }, 37 | { 38 | "description": "boundary point integer is valid", 39 | "data": 300, 40 | "valid": true 41 | }, 42 | { 43 | "description": "boundary point float is valid", 44 | "data": 300.00, 45 | "valid": true 46 | }, 47 | { 48 | "description": "above the maximum is invalid", 49 | "data": 300.5, 50 | "valid": false 51 | } 52 | ] 53 | } 54 | ] 55 | -------------------------------------------------------------------------------- /testdata/draft7/minItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minItems validation", 4 | "schema": {"minItems": 1}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": [1, 2], 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": [1], 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": [], 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-arrays", 23 | "data": "", 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /testdata/draft7/minLength.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minLength validation", 4 | "schema": {"minLength": 2}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": "foo", 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": "fo", 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": "f", 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-strings", 23 | "data": 1, 24 | "valid": true 25 | }, 26 | { 27 | "description": "one supplementary Unicode code point is not long enough", 28 | "data": "\uD83D\uDCA9", 29 | "valid": false 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /testdata/draft7/minProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minProperties validation", 4 | "schema": {"minProperties": 1}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": {"foo": 1, "bar": 2}, 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": {"foo": 1}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": {}, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores arrays", 23 | "data": [], 24 | "valid": true 25 | }, 26 | { 27 | "description": "ignores strings", 28 | "data": "", 29 | "valid": true 30 | }, 31 | { 32 | "description": "ignores other non-objects", 33 | "data": 12, 34 | "valid": true 35 | } 36 | ] 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /testdata/draft7/minimum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minimum validation", 4 | "schema": {"minimum": 1.1}, 5 | "tests": [ 6 | { 7 | "description": "above the minimum is valid", 8 | "data": 2.6, 9 | "valid": true 10 | }, 11 | { 12 | "description": "boundary point is valid", 13 | "data": 1.1, 14 | "valid": true 15 | }, 16 | { 17 | "description": "below the minimum is invalid", 18 | "data": 0.6, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-numbers", 23 | "data": "x", 24 | "valid": true 25 | } 26 | ] 27 | }, 28 | { 29 | "description": "minimum validation with signed integer", 30 | "schema": {"minimum": -2}, 31 | "tests": [ 32 | { 33 | "description": "negative above the minimum is valid", 34 | "data": -1, 35 | "valid": true 36 | }, 37 | { 38 | "description": "positive above the minimum is valid", 39 | "data": 0, 40 | "valid": true 41 | }, 42 | { 43 | "description": "boundary point is valid", 44 | "data": -2, 45 | "valid": true 46 | }, 47 | { 48 | "description": "boundary point with float is valid", 49 | "data": -2.0, 50 | "valid": true 51 | }, 52 | { 53 | "description": "float below the minimum is invalid", 54 | "data": -2.0001, 55 | "valid": false 56 | }, 57 | { 58 | "description": "int below the minimum is invalid", 59 | "data": -3, 60 | "valid": false 61 | }, 62 | { 63 | "description": "ignores non-numbers", 64 | "data": "x", 65 | "valid": true 66 | } 67 | ] 68 | } 69 | ] 70 | -------------------------------------------------------------------------------- /testdata/draft7/multipleOf.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "by int", 4 | "schema": {"multipleOf": 2}, 5 | "tests": [ 6 | { 7 | "description": "int by int", 8 | "data": 10, 9 | "valid": true 10 | }, 11 | { 12 | "description": "int by int fail", 13 | "data": 7, 14 | "valid": false 15 | }, 16 | { 17 | "description": "ignores non-numbers", 18 | "data": "foo", 19 | "valid": true 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "by number", 25 | "schema": {"multipleOf": 1.5}, 26 | "tests": [ 27 | { 28 | "description": "zero is multiple of anything", 29 | "data": 0, 30 | "valid": true 31 | }, 32 | { 33 | "description": "4.5 is multiple of 1.5", 34 | "data": 4.5, 35 | "valid": true 36 | }, 37 | { 38 | "description": "35 is not multiple of 1.5", 39 | "data": 35, 40 | "valid": false 41 | } 42 | ] 43 | }, 44 | { 45 | "description": "by small number", 46 | "schema": {"multipleOf": 0.0001}, 47 | "tests": [ 48 | { 49 | "description": "0.0075 is multiple of 0.0001", 50 | "data": 0.0075, 51 | "valid": true 52 | }, 53 | { 54 | "description": "0.00751 is not multiple of 0.0001", 55 | "data": 0.00751, 56 | "valid": false 57 | } 58 | ] 59 | } 60 | ] 61 | -------------------------------------------------------------------------------- /testdata/draft7/optional/content.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of string-encoded content based on media type", 4 | "schema": { 5 | "contentMediaType": "application/json" 6 | }, 7 | "tests": [ 8 | { 9 | "description": "a valid JSON document", 10 | "data": "{\"foo\": \"bar\"}", 11 | "valid": true 12 | }, 13 | { 14 | "description": "an invalid JSON document", 15 | "data": "{:}", 16 | "valid": false 17 | }, 18 | { 19 | "description": "ignores non-strings", 20 | "data": 100, 21 | "valid": true 22 | } 23 | ] 24 | }, 25 | { 26 | "description": "validation of binary string-encoding", 27 | "schema": { 28 | "contentEncoding": "base64" 29 | }, 30 | "tests": [ 31 | { 32 | "description": "a valid base64 string", 33 | "data": "eyJmb28iOiAiYmFyIn0K", 34 | "valid": true 35 | }, 36 | { 37 | "description": "an invalid base64 string (% is not a valid character)", 38 | "data": "eyJmb28iOi%iYmFyIn0K", 39 | "valid": false 40 | }, 41 | { 42 | "description": "ignores non-strings", 43 | "data": 100, 44 | "valid": true 45 | } 46 | ] 47 | }, 48 | { 49 | "description": "validation of binary-encoded media type documents", 50 | "schema": { 51 | "contentMediaType": "application/json", 52 | "contentEncoding": "base64" 53 | }, 54 | "tests": [ 55 | { 56 | "description": "a valid base64-encoded JSON document", 57 | "data": "eyJmb28iOiAiYmFyIn0K", 58 | "valid": true 59 | }, 60 | { 61 | "description": "a validly-encoded invalid JSON document", 62 | "data": "ezp9Cg==", 63 | "valid": false 64 | }, 65 | { 66 | "description": "an invalid base64 string that is valid JSON", 67 | "data": "{}", 68 | "valid": false 69 | }, 70 | { 71 | "description": "ignores non-strings", 72 | "data": 100, 73 | "valid": true 74 | } 75 | ] 76 | } 77 | ] 78 | -------------------------------------------------------------------------------- /testdata/draft7/optional/format/date-time.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of date-time strings", 4 | "schema": {"format": "date-time"}, 5 | "tests": [ 6 | { 7 | "description": "a valid date-time string", 8 | "data": "1963-06-19T08:30:06.283185Z", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a valid date-time string without second fraction", 13 | "data": "1963-06-19T08:30:06Z", 14 | "valid": true 15 | }, 16 | { 17 | "description": "a valid date-time string with plus offset", 18 | "data": "1937-01-01T12:00:27.87+00:20", 19 | "valid": true 20 | }, 21 | { 22 | "description": "a valid date-time string with minus offset", 23 | "data": "1990-12-31T15:59:50.123-08:00", 24 | "valid": true 25 | }, 26 | { 27 | "description": "a invalid day in date-time string", 28 | "data": "1990-02-31T15:59:60.123-08:00", 29 | "valid": false 30 | }, 31 | { 32 | "description": "an invalid offset in date-time string", 33 | "data": "1990-12-31T15:59:60-24:00", 34 | "valid": false 35 | }, 36 | { 37 | "description": "an invalid date-time string", 38 | "data": "06/19/1963 08:30:06 PST", 39 | "valid": false 40 | }, 41 | { 42 | "description": "case-insensitive T and Z", 43 | "data": "1963-06-19t08:30:06.283185z", 44 | "valid": true 45 | }, 46 | { 47 | "description": "only RFC3339 not all of ISO 8601 are valid", 48 | "data": "2013-350T01:01:01", 49 | "valid": false 50 | } 51 | ] 52 | } 53 | ] 54 | -------------------------------------------------------------------------------- /testdata/draft7/optional/format/date.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of date strings", 4 | "schema": {"format": "date"}, 5 | "tests": [ 6 | { 7 | "description": "a valid date string", 8 | "data": "1963-06-19", 9 | "valid": true 10 | }, 11 | { 12 | "description": "an invalid date-time string", 13 | "data": "06/19/1963", 14 | "valid": false 15 | }, 16 | { 17 | "description": "only RFC3339 not all of ISO 8601 are valid", 18 | "data": "2013-350", 19 | "valid": false 20 | } 21 | ] 22 | } 23 | ] 24 | -------------------------------------------------------------------------------- /testdata/draft7/optional/format/email.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of e-mail addresses", 4 | "schema": {"format": "email"}, 5 | "tests": [ 6 | { 7 | "description": "a valid e-mail address", 8 | "data": "joe.bloggs@example.com", 9 | "valid": true 10 | }, 11 | { 12 | "description": "an invalid e-mail address", 13 | "data": "2962", 14 | "valid": false 15 | } 16 | ] 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /testdata/draft7/optional/format/hostname.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of host names", 4 | "schema": {"format": "hostname"}, 5 | "tests": [ 6 | { 7 | "description": "a valid host name", 8 | "data": "www.example.com", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a valid punycoded IDN hostname", 13 | "data": "xn--4gbwdl.xn--wgbh1c", 14 | "valid": true 15 | }, 16 | { 17 | "description": "a host name starting with an illegal character", 18 | "data": "-a-host-name-that-starts-with--", 19 | "valid": false 20 | }, 21 | { 22 | "description": "a host name containing illegal characters", 23 | "data": "not_a_valid_host_name", 24 | "valid": false 25 | }, 26 | { 27 | "description": "a host name with a component too long", 28 | "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component", 29 | "valid": false 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /testdata/draft7/optional/format/idn-email.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of an internationalized e-mail addresses", 4 | "schema": {"format": "idn-email"}, 5 | "tests": [ 6 | { 7 | "description": "a valid idn e-mail (example@example.test in Hangul)", 8 | "data": "실례@실례.테스트", 9 | "valid": true 10 | }, 11 | { 12 | "description": "an invalid idn e-mail address", 13 | "data": "2962", 14 | "valid": false 15 | } 16 | ] 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /testdata/draft7/optional/format/idn-hostname.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of internationalized host names", 4 | "schema": {"format": "idn-hostname"}, 5 | "tests": [ 6 | { 7 | "description": "a valid host name (example.test in Hangul)", 8 | "data": "실례.테스트", 9 | "valid": true 10 | }, 11 | { 12 | "description": "illegal first char U+302E Hangul single dot tone mark", 13 | "data": "〮실례.테스트", 14 | "valid": false 15 | }, 16 | { 17 | "description": "contains illegal char U+302E Hangul single dot tone mark", 18 | "data": "실〮례.테스트", 19 | "valid": false 20 | }, 21 | { 22 | "description": "a host name with a component too long", 23 | "data": "실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실례례테스트례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례테스트례례실례.테스트", 24 | "valid": false 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /testdata/draft7/optional/format/ipv4.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of IP addresses", 4 | "schema": {"format": "ipv4"}, 5 | "tests": [ 6 | { 7 | "description": "a valid IP address", 8 | "data": "192.168.0.1", 9 | "valid": true 10 | }, 11 | { 12 | "description": "an IP address with too many components", 13 | "data": "127.0.0.0.1", 14 | "valid": false 15 | }, 16 | { 17 | "description": "an IP address with out-of-range values", 18 | "data": "256.256.256.256", 19 | "valid": false 20 | }, 21 | { 22 | "description": "an IP address without 4 components", 23 | "data": "127.0", 24 | "valid": false 25 | }, 26 | { 27 | "description": "an IP address as an integer", 28 | "data": "0x7f000001", 29 | "valid": false 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /testdata/draft7/optional/format/ipv6.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of IPv6 addresses", 4 | "schema": {"format": "ipv6"}, 5 | "tests": [ 6 | { 7 | "description": "a valid IPv6 address", 8 | "data": "::1", 9 | "valid": true 10 | }, 11 | { 12 | "description": "an IPv6 address with out-of-range values", 13 | "data": "12345::", 14 | "valid": false 15 | }, 16 | { 17 | "description": "an IPv6 address with too many components", 18 | "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1", 19 | "valid": false 20 | }, 21 | { 22 | "description": "an IPv6 address containing illegal characters", 23 | "data": "::laptop", 24 | "valid": false 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /testdata/draft7/optional/format/iri-reference.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of IRI References", 4 | "schema": {"format": "iri-reference"}, 5 | "tests": [ 6 | { 7 | "description": "a valid IRI", 8 | "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a valid protocol-relative IRI Reference", 13 | "data": "//ƒøø.ßår/?∂éœ=πîx#πîüx", 14 | "valid": true 15 | }, 16 | { 17 | "description": "a valid relative IRI Reference", 18 | "data": "/âππ", 19 | "valid": true 20 | }, 21 | { 22 | "description": "an invalid IRI Reference", 23 | "data": "\\\\WINDOWS\\filëßåré", 24 | "valid": false 25 | }, 26 | { 27 | "description": "a valid IRI Reference", 28 | "data": "âππ", 29 | "valid": true 30 | }, 31 | { 32 | "description": "a valid IRI fragment", 33 | "data": "#ƒrägmênt", 34 | "valid": true 35 | }, 36 | { 37 | "description": "an invalid IRI fragment", 38 | "data": "#ƒräg\\mênt", 39 | "valid": false 40 | } 41 | ] 42 | } 43 | ] 44 | -------------------------------------------------------------------------------- /testdata/draft7/optional/format/iri.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of IRIs", 4 | "schema": {"format": "iri"}, 5 | "tests": [ 6 | { 7 | "description": "a valid IRI with anchor tag", 8 | "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a valid IRI with anchor tag and parantheses", 13 | "data": "http://ƒøø.com/blah_(wîkïpédiå)_blah#ßité-1", 14 | "valid": true 15 | }, 16 | { 17 | "description": "a valid IRI with URL-encoded stuff", 18 | "data": "http://ƒøø.ßår/?q=Test%20URL-encoded%20stuff", 19 | "valid": true 20 | }, 21 | { 22 | "description": "a valid IRI with many special characters", 23 | "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com", 24 | "valid": true 25 | }, 26 | { 27 | "description": "a valid IRI based on IPv6", 28 | "data": "http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]", 29 | "valid": true 30 | }, 31 | { 32 | "description": "an invalid IRI based on IPv6", 33 | "data": "http://2001:0db8:85a3:0000:0000:8a2e:0370:7334", 34 | "valid": false 35 | }, 36 | { 37 | "description": "an invalid relative IRI Reference", 38 | "data": "/abc", 39 | "valid": false 40 | }, 41 | { 42 | "description": "an invalid IRI", 43 | "data": "\\\\WINDOWS\\filëßåré", 44 | "valid": false 45 | }, 46 | { 47 | "description": "an invalid IRI though valid IRI reference", 48 | "data": "âππ", 49 | "valid": false 50 | } 51 | ] 52 | } 53 | ] 54 | -------------------------------------------------------------------------------- /testdata/draft7/optional/format/regex.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of regular expressions", 4 | "schema": {"format": "regex"}, 5 | "tests": [ 6 | { 7 | "description": "a valid regular expression", 8 | "data": "([abc])+\\s+$", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a regular expression with unclosed parens is invalid", 13 | "data": "^(abc]", 14 | "valid": false 15 | } 16 | ] 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /testdata/draft7/optional/format/relative-json-pointer.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of Relative JSON Pointers (RJP)", 4 | "schema": {"format": "relative-json-pointer"}, 5 | "tests": [ 6 | { 7 | "description": "a valid upwards RJP", 8 | "data": "1", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a valid downwards RJP", 13 | "data": "0/foo/bar", 14 | "valid": true 15 | }, 16 | { 17 | "description": "a valid up and then down RJP, with array index", 18 | "data": "2/0/baz/1/zip", 19 | "valid": true 20 | }, 21 | { 22 | "description": "a valid RJP taking the member or index name", 23 | "data": "0#", 24 | "valid": true 25 | }, 26 | { 27 | "description": "an invalid RJP that is a valid JSON Pointer", 28 | "data": "/foo/bar", 29 | "valid": false 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /testdata/draft7/optional/format/time.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of time strings", 4 | "schema": {"format": "time"}, 5 | "tests": [ 6 | { 7 | "description": "a valid time string", 8 | "data": "08:30:06.283185Z", 9 | "valid": true 10 | }, 11 | { 12 | "description": "an invalid time string", 13 | "data": "08:30:06 PST", 14 | "valid": false 15 | }, 16 | { 17 | "description": "only RFC3339 not all of ISO 8601 are valid", 18 | "data": "01:01:01,1111", 19 | "valid": false 20 | } 21 | ] 22 | } 23 | ] 24 | -------------------------------------------------------------------------------- /testdata/draft7/optional/format/uri-reference.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "validation of URI References", 4 | "schema": {"format": "uri-reference"}, 5 | "tests": [ 6 | { 7 | "description": "a valid URI", 8 | "data": "http://foo.bar/?baz=qux#quux", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a valid protocol-relative URI Reference", 13 | "data": "//foo.bar/?baz=qux#quux", 14 | "valid": true 15 | }, 16 | { 17 | "description": "a valid relative URI Reference", 18 | "data": "/abc", 19 | "valid": true 20 | }, 21 | { 22 | "description": "an invalid URI Reference", 23 | "data": "\\\\WINDOWS\\fileshare", 24 | "valid": false 25 | }, 26 | { 27 | "description": "a valid URI Reference", 28 | "data": "abc", 29 | "valid": true 30 | }, 31 | { 32 | "description": "a valid URI fragment", 33 | "data": "#fragment", 34 | "valid": true 35 | }, 36 | { 37 | "description": "an invalid URI fragment", 38 | "data": "#frag\\ment", 39 | "valid": false 40 | } 41 | ] 42 | } 43 | ] 44 | -------------------------------------------------------------------------------- /testdata/draft7/optional/format/uri-template.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "format: uri-template", 4 | "schema": {"format": "uri-template"}, 5 | "tests": [ 6 | { 7 | "description": "a valid uri-template", 8 | "data": "http://example.com/dictionary/{term:1}/{term}", 9 | "valid": true 10 | }, 11 | { 12 | "description": "an invalid uri-template", 13 | "data": "http://example.com/dictionary/{term:1}/{term", 14 | "valid": false 15 | }, 16 | { 17 | "description": "a valid uri-template without variables", 18 | "data": "http://example.com/dictionary", 19 | "valid": true 20 | }, 21 | { 22 | "description": "a valid relative uri-template", 23 | "data": "dictionary/{term:1}/{term}", 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /testdata/draft7/optional/zeroTerminatedFloats.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "some languages do not distinguish between different types of numeric value", 4 | "schema": { 5 | "type": "integer" 6 | }, 7 | "tests": [ 8 | { 9 | "description": "a float without fractional part is an integer", 10 | "data": 1.0, 11 | "valid": true 12 | } 13 | ] 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /testdata/draft7/pattern.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "pattern validation", 4 | "schema": {"pattern": "^a*$"}, 5 | "tests": [ 6 | { 7 | "description": "a matching pattern is valid", 8 | "data": "aaa", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a non-matching pattern is invalid", 13 | "data": "abc", 14 | "valid": false 15 | }, 16 | { 17 | "description": "ignores non-strings", 18 | "data": true, 19 | "valid": true 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "pattern is not anchored", 25 | "schema": {"pattern": "a+"}, 26 | "tests": [ 27 | { 28 | "description": "matches a substring", 29 | "data": "xxaayy", 30 | "valid": true 31 | } 32 | ] 33 | } 34 | ] 35 | -------------------------------------------------------------------------------- /testdata/draft7/propertyNames.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "propertyNames validation", 4 | "schema": { 5 | "propertyNames": {"maxLength": 3} 6 | }, 7 | "tests": [ 8 | { 9 | "description": "all property names valid", 10 | "data": { 11 | "f": {}, 12 | "foo": {} 13 | }, 14 | "valid": true 15 | }, 16 | { 17 | "description": "some property names invalid", 18 | "data": { 19 | "foo": {}, 20 | "foobar": {} 21 | }, 22 | "valid": false 23 | }, 24 | { 25 | "description": "object without properties is valid", 26 | "data": {}, 27 | "valid": true 28 | }, 29 | { 30 | "description": "ignores arrays", 31 | "data": [1, 2, 3, 4], 32 | "valid": true 33 | }, 34 | { 35 | "description": "ignores strings", 36 | "data": "foobar", 37 | "valid": true 38 | }, 39 | { 40 | "description": "ignores other non-objects", 41 | "data": 12, 42 | "valid": true 43 | } 44 | ] 45 | }, 46 | { 47 | "description": "propertyNames with boolean schema true", 48 | "schema": {"propertyNames": true}, 49 | "tests": [ 50 | { 51 | "description": "object with any properties is valid", 52 | "data": {"foo": 1}, 53 | "valid": true 54 | }, 55 | { 56 | "description": "empty object is valid", 57 | "data": {}, 58 | "valid": true 59 | } 60 | ] 61 | }, 62 | { 63 | "description": "propertyNames with boolean schema false", 64 | "schema": {"propertyNames": false}, 65 | "tests": [ 66 | { 67 | "description": "object with any properties is invalid", 68 | "data": {"foo": 1}, 69 | "valid": false 70 | }, 71 | { 72 | "description": "empty object is valid", 73 | "data": {}, 74 | "valid": true 75 | } 76 | ] 77 | } 78 | ] 79 | -------------------------------------------------------------------------------- /testdata/draft7/required.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "required validation", 4 | "schema": { 5 | "properties": { 6 | "foo": {}, 7 | "bar": {} 8 | }, 9 | "required": ["foo"] 10 | }, 11 | "tests": [ 12 | { 13 | "description": "present required property is valid", 14 | "data": {"foo": 1}, 15 | "valid": true 16 | }, 17 | { 18 | "description": "non-present required property is invalid", 19 | "data": {"bar": 1}, 20 | "valid": false 21 | }, 22 | { 23 | "description": "ignores arrays", 24 | "data": [], 25 | "valid": true 26 | }, 27 | { 28 | "description": "ignores strings", 29 | "data": "", 30 | "valid": true 31 | }, 32 | { 33 | "description": "ignores other non-objects", 34 | "data": 12, 35 | "valid": true 36 | } 37 | ] 38 | }, 39 | { 40 | "description": "required default validation", 41 | "schema": { 42 | "properties": { 43 | "foo": {} 44 | } 45 | }, 46 | "tests": [ 47 | { 48 | "description": "not required by default", 49 | "data": {}, 50 | "valid": true 51 | } 52 | ] 53 | }, 54 | { 55 | "description": "required with empty array", 56 | "schema": { 57 | "properties": { 58 | "foo": {} 59 | }, 60 | "required": [] 61 | }, 62 | "tests": [ 63 | { 64 | "description": "property not required", 65 | "data": {}, 66 | "valid": true 67 | } 68 | ] 69 | }, 70 | { 71 | "description": "required with escaped characters", 72 | "schema": { 73 | "required": [ 74 | "foo\nbar", 75 | "foo\"bar", 76 | "foo\\bar", 77 | "foo\rbar", 78 | "foo\tbar", 79 | "foo\fbar" 80 | ] 81 | }, 82 | "tests": [ 83 | { 84 | "description": "object with all properties present is valid", 85 | "data": { 86 | "foo\nbar": 1, 87 | "foo\"bar": 1, 88 | "foo\\bar": 1, 89 | "foo\rbar": 1, 90 | "foo\tbar": 1, 91 | "foo\fbar": 1 92 | }, 93 | "valid": true 94 | }, 95 | { 96 | "description": "object with some properties missing is invalid", 97 | "data": { 98 | "foo\nbar": "1", 99 | "foo\"bar": "1" 100 | }, 101 | "valid": false 102 | } 103 | ] 104 | } 105 | ] 106 | -------------------------------------------------------------------------------- /testdata/meta/applicator.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "$id": "https://json-schema.org/draft/2019-09/meta/applicator", 4 | "$vocabulary": { 5 | "https://json-schema.org/draft/2019-09/vocab/applicator": true 6 | }, 7 | "$recursiveAnchor": true, 8 | 9 | "title": "Applicator vocabulary meta-schema", 10 | "properties": { 11 | "additionalItems": { "$recursiveRef": "#" }, 12 | "unevaluatedItems": { "$recursiveRef": "#" }, 13 | "items": { 14 | "anyOf": [ 15 | { "$recursiveRef": "#" }, 16 | { "$ref": "#/$defs/schemaArray" } 17 | ] 18 | }, 19 | "contains": { "$recursiveRef": "#" }, 20 | "additionalProperties": { "$recursiveRef": "#" }, 21 | "unevaluatedProperties": { "$recursiveRef": "#" }, 22 | "properties": { 23 | "type": "object", 24 | "additionalProperties": { "$recursiveRef": "#" }, 25 | "default": {} 26 | }, 27 | "patternProperties": { 28 | "type": "object", 29 | "additionalProperties": { "$recursiveRef": "#" }, 30 | "propertyNames": { "format": "regex" }, 31 | "default": {} 32 | }, 33 | "dependentSchemas": { 34 | "type": "object", 35 | "additionalProperties": { 36 | "$recursiveRef": "#" 37 | } 38 | }, 39 | "propertyNames": { "$recursiveRef": "#" }, 40 | "if": { "$recursiveRef": "#" }, 41 | "then": { "$recursiveRef": "#" }, 42 | "else": { "$recursiveRef": "#" }, 43 | "allOf": { "$ref": "#/$defs/schemaArray" }, 44 | "anyOf": { "$ref": "#/$defs/schemaArray" }, 45 | "oneOf": { "$ref": "#/$defs/schemaArray" }, 46 | "not": { "$recursiveRef": "#" } 47 | }, 48 | "$defs": { 49 | "schemaArray": { 50 | "type": "array", 51 | "minItems": 1, 52 | "items": { "$recursiveRef": "#" } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /testdata/meta/content.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "$id": "https://json-schema.org/draft/2019-09/meta/content", 4 | "$vocabulary": { 5 | "https://json-schema.org/draft/2019-09/vocab/content": true 6 | }, 7 | "$recursiveAnchor": true, 8 | 9 | "title": "Content vocabulary meta-schema", 10 | 11 | "type": ["object", "boolean"], 12 | "properties": { 13 | "contentMediaType": { "type": "string" }, 14 | "contentEncoding": { "type": "string" }, 15 | "contentSchema": { "$recursiveRef": "#" } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /testdata/meta/core.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "$id": "https://json-schema.org/draft/2019-09/meta/core", 4 | "$vocabulary": { 5 | "https://json-schema.org/draft/2019-09/vocab/core": true 6 | }, 7 | "$recursiveAnchor": true, 8 | 9 | "title": "Core vocabulary meta-schema", 10 | "type": ["object", "boolean"], 11 | "properties": { 12 | "$id": { 13 | "type": "string", 14 | "format": "uri-reference", 15 | "$comment": "Non-empty fragments not allowed.", 16 | "pattern": "^[^#]*#?$" 17 | }, 18 | "$schema": { 19 | "type": "string", 20 | "format": "uri" 21 | }, 22 | "$anchor": { 23 | "type": "string", 24 | "pattern": "^[A-Za-z][-A-Za-z0-9.:_]*$" 25 | }, 26 | "$ref": { 27 | "type": "string", 28 | "format": "uri-reference" 29 | }, 30 | "$recursiveRef": { 31 | "type": "string", 32 | "format": "uri-reference" 33 | }, 34 | "$recursiveAnchor": { 35 | "type": "boolean", 36 | "const": true, 37 | "default": false 38 | }, 39 | "$vocabulary": { 40 | "type": "object", 41 | "propertyNames": { 42 | "type": "string", 43 | "format": "uri" 44 | }, 45 | "additionalProperties": { 46 | "type": "boolean" 47 | } 48 | }, 49 | "$comment": { 50 | "type": "string" 51 | }, 52 | "$defs": { 53 | "type": "object", 54 | "additionalProperties": { "$recursiveRef": "#" }, 55 | "default": {} 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /testdata/meta/format.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "$id": "https://json-schema.org/draft/2019-09/meta/format", 4 | "$vocabulary": { 5 | "https://json-schema.org/draft/2019-09/vocab/format": true 6 | }, 7 | "$recursiveAnchor": true, 8 | 9 | "title": "Format vocabulary meta-schema", 10 | "type": ["object", "boolean"], 11 | "properties": { 12 | "format": { "type": "string" } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /testdata/meta/hyper-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/hyper-schema", 3 | "$id": "https://json-schema.org/draft/2019-09/meta/hyper-schema", 4 | "$vocabulary": { 5 | "https://json-schema.org/draft/2019-09/vocab/hyper-schema": true 6 | }, 7 | "$recursiveAnchor": true, 8 | 9 | "title": "JSON Hyper-Schema Vocabulary Schema", 10 | "type": ["object", "boolean"], 11 | "properties": { 12 | "base": { 13 | "type": "string", 14 | "format": "uri-template" 15 | }, 16 | "links": { 17 | "type": "array", 18 | "items": { 19 | "$ref": "https://json-schema.org/draft/2019-09/links" 20 | } 21 | } 22 | }, 23 | "links": [ 24 | { 25 | "rel": "self", 26 | "href": "{+%24id}" 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /testdata/meta/meta-data.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "$id": "https://json-schema.org/draft/2019-09/meta/meta-data", 4 | "$vocabulary": { 5 | "https://json-schema.org/draft/2019-09/vocab/meta-data": true 6 | }, 7 | "$recursiveAnchor": true, 8 | 9 | "title": "Meta-data vocabulary meta-schema", 10 | 11 | "type": ["object", "boolean"], 12 | "properties": { 13 | "title": { 14 | "type": "string" 15 | }, 16 | "description": { 17 | "type": "string" 18 | }, 19 | "default": true, 20 | "deprecated": { 21 | "type": "boolean", 22 | "default": false 23 | }, 24 | "readOnly": { 25 | "type": "boolean", 26 | "default": false 27 | }, 28 | "writeOnly": { 29 | "type": "boolean", 30 | "default": false 31 | }, 32 | "examples": { 33 | "type": "array", 34 | "items": true 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /testdata/meta/validation.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "$id": "https://json-schema.org/draft/2019-09/meta/validation", 4 | "$vocabulary": { 5 | "https://json-schema.org/draft/2019-09/vocab/validation": true 6 | }, 7 | "$recursiveAnchor": true, 8 | 9 | "title": "Validation vocabulary meta-schema", 10 | "type": ["object", "boolean"], 11 | "properties": { 12 | "multipleOf": { 13 | "type": "number", 14 | "exclusiveMinimum": 0 15 | }, 16 | "maximum": { 17 | "type": "number" 18 | }, 19 | "exclusiveMaximum": { 20 | "type": "number" 21 | }, 22 | "minimum": { 23 | "type": "number" 24 | }, 25 | "exclusiveMinimum": { 26 | "type": "number" 27 | }, 28 | "maxLength": { "$ref": "#/$defs/nonNegativeInteger" }, 29 | "minLength": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, 30 | "pattern": { 31 | "type": "string", 32 | "format": "regex" 33 | }, 34 | "maxItems": { "$ref": "#/$defs/nonNegativeInteger" }, 35 | "minItems": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, 36 | "uniqueItems": { 37 | "type": "boolean", 38 | "default": false 39 | }, 40 | "maxContains": { "$ref": "#/$defs/nonNegativeInteger" }, 41 | "minContains": { 42 | "$ref": "#/$defs/nonNegativeInteger", 43 | "default": 1 44 | }, 45 | "maxProperties": { "$ref": "#/$defs/nonNegativeInteger" }, 46 | "minProperties": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, 47 | "required": { "$ref": "#/$defs/stringArray" }, 48 | "dependentRequired": { 49 | "type": "object", 50 | "additionalProperties": { 51 | "$ref": "#/$defs/stringArray" 52 | } 53 | }, 54 | "const": true, 55 | "enum": { 56 | "type": "array", 57 | "items": true 58 | }, 59 | "type": { 60 | "anyOf": [ 61 | { "$ref": "#/$defs/simpleTypes" }, 62 | { 63 | "type": "array", 64 | "items": { "$ref": "#/$defs/simpleTypes" }, 65 | "minItems": 1, 66 | "uniqueItems": true 67 | } 68 | ] 69 | } 70 | }, 71 | "$defs": { 72 | "nonNegativeInteger": { 73 | "type": "integer", 74 | "minimum": 0 75 | }, 76 | "nonNegativeIntegerDefault0": { 77 | "$ref": "#/$defs/nonNegativeInteger", 78 | "default": 0 79 | }, 80 | "simpleTypes": { 81 | "enum": [ 82 | "array", 83 | "boolean", 84 | "integer", 85 | "null", 86 | "number", 87 | "object", 88 | "string" 89 | ] 90 | }, 91 | "stringArray": { 92 | "type": "array", 93 | "items": { "type": "string" }, 94 | "uniqueItems": true, 95 | "default": [] 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /testdata/remotes/folder/folderInteger.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer" 3 | } 4 | -------------------------------------------------------------------------------- /testdata/remotes/integer.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer" 3 | } 4 | -------------------------------------------------------------------------------- /testdata/remotes/name-defs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$defs": { 3 | "orNull": { 4 | "anyOf": [ 5 | { 6 | "type": "null" 7 | }, 8 | { 9 | "$ref": "#" 10 | } 11 | ] 12 | } 13 | }, 14 | "type": "string" 15 | } 16 | -------------------------------------------------------------------------------- /testdata/remotes/name.json: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": { 3 | "orNull": { 4 | "anyOf": [ 5 | { 6 | "type": "null" 7 | }, 8 | { 9 | "$ref": "#" 10 | } 11 | ] 12 | } 13 | }, 14 | "type": "string" 15 | } 16 | -------------------------------------------------------------------------------- /testdata/remotes/subSchemas-defs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$defs": { 3 | "integer": { 4 | "type": "integer" 5 | }, 6 | "refToInteger": { 7 | "$ref": "#/$defs/integer" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /testdata/remotes/subSchemas.json: -------------------------------------------------------------------------------- 1 | { 2 | "integer": { 3 | "type": "integer" 4 | }, 5 | "refToInteger": { 6 | "$ref": "#/integer" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /traversal.go: -------------------------------------------------------------------------------- 1 | package jsonschema 2 | 3 | // JSONPather makes validators traversible by JSON-pointers, 4 | // which is required to support references in JSON schemas. 5 | type JSONPather interface { 6 | // JSONProp take a string references for a given JSON property 7 | // implementations must return any matching property of that name 8 | // or nil if no such subproperty exists. 9 | // Note this also applies to array values, which are expected to interpret 10 | // valid numbers as an array index 11 | JSONProp(name string) interface{} 12 | } 13 | 14 | // JSONContainer is an interface that enables tree traversal by listing 15 | // the immideate children of an object 16 | type JSONContainer interface { 17 | // JSONChildren should return all immidiate children of this element 18 | JSONChildren() map[string]JSONPather 19 | } 20 | 21 | func walkJSON(elem JSONPather, fn func(elem JSONPather) error) error { 22 | if err := fn(elem); err != nil { 23 | return err 24 | } 25 | 26 | if con, ok := elem.(JSONContainer); ok { 27 | for _, ch := range con.JSONChildren() { 28 | if err := walkJSON(ch, fn); err != nil { 29 | return err 30 | } 31 | } 32 | } 33 | 34 | return nil 35 | } 36 | -------------------------------------------------------------------------------- /traversal_test.go: -------------------------------------------------------------------------------- 1 | package jsonschema 2 | 3 | import ( 4 | "context" 5 | "io/ioutil" 6 | "testing" 7 | ) 8 | 9 | func TestSchemaDeref(t *testing.T) { 10 | ctx := context.Background() 11 | sch := []byte(`{ 12 | "$defs": { 13 | "a": {"type": "integer"}, 14 | "b": {"$ref": "#/$defs/a"}, 15 | "c": {"$ref": "#/$defs/b"} 16 | }, 17 | "$ref": "#/$defs/c" 18 | }`) 19 | 20 | rs := &Schema{} 21 | if err := rs.UnmarshalJSON(sch); err != nil { 22 | t.Errorf("unexpected unmarshal error: %s", err.Error()) 23 | return 24 | } 25 | 26 | got, err := rs.ValidateBytes(ctx, []byte(`"a"`)) 27 | if err != nil { 28 | t.Errorf("error validating bytes: %s", err.Error()) 29 | return 30 | } 31 | 32 | if got == nil { 33 | t.Errorf("expected error, got nil") 34 | return 35 | } 36 | } 37 | 38 | func TestReferenceTraversal(t *testing.T) { 39 | sch, err := ioutil.ReadFile("testdata/draft2019-09_schema.json") 40 | if err != nil { 41 | t.Errorf("error reading file: %s", err.Error()) 42 | return 43 | } 44 | 45 | rs := &Schema{} 46 | if err := rs.UnmarshalJSON(sch); err != nil { 47 | t.Errorf("unexpected unmarshal error: %s", err.Error()) 48 | return 49 | } 50 | 51 | elements := 0 52 | expectElements := 14 53 | refs := 0 54 | expectRefs := 6 55 | walkJSON(rs, func(elem JSONPather) error { 56 | elements++ 57 | if sch, ok := elem.(*Schema); ok { 58 | if sch.HasKeyword("$ref") { 59 | refs++ 60 | } 61 | } 62 | return nil 63 | }) 64 | 65 | if elements != expectElements { 66 | t.Errorf("expected %d elements, got: %d", expectElements, elements) 67 | } 68 | if refs != expectRefs { 69 | t.Errorf("expected %d references, got: %d", expectRefs, refs) 70 | } 71 | 72 | cases := []struct { 73 | input string 74 | elements int 75 | refs int 76 | }{ 77 | {`{ "not" : { "$ref":"#" }}`, 2, 0}, 78 | } 79 | 80 | for i, c := range cases { 81 | rs := &Schema{} 82 | if err := rs.UnmarshalJSON([]byte(c.input)); err != nil { 83 | t.Errorf("unexpected unmarshal error: %s", err.Error()) 84 | return 85 | } 86 | 87 | elements := 0 88 | refs := 0 89 | walkJSON(rs, func(elem JSONPather) error { 90 | elements++ 91 | if sch, ok := elem.(*Schema); ok { 92 | if sch.HasKeyword("$ref") { 93 | refs++ 94 | } 95 | } 96 | return nil 97 | }) 98 | if elements != c.elements { 99 | t.Errorf("case %d: expected %d elements, got: %d", i, c.elements, elements) 100 | } 101 | if refs != c.refs { 102 | t.Errorf("case %d: expected %d references, got: %d", i, c.refs, refs) 103 | } 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /util.go: -------------------------------------------------------------------------------- 1 | package jsonschema 2 | 3 | import ( 4 | "fmt" 5 | "net/url" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | var showDebug = os.Getenv("JSON_SCHEMA_DEBUG") == "1" 11 | 12 | // schemaDebug provides a logging interface 13 | // which is off by defauly but can be activated 14 | // for debuging purposes 15 | func schemaDebug(message string, args ...interface{}) { 16 | if showDebug { 17 | if message[len(message)-1] != '\n' { 18 | message += "\n" 19 | } 20 | fmt.Printf(message, args...) 21 | } 22 | } 23 | 24 | // SafeResolveURL resolves a string url against the current context url 25 | func SafeResolveURL(ctxURL, resURL string) (string, error) { 26 | cu, err := url.Parse(ctxURL) 27 | if err != nil { 28 | return "", err 29 | } 30 | u, err := url.Parse(resURL) 31 | if err != nil { 32 | return "", err 33 | } 34 | resolvedURL := cu.ResolveReference(u) 35 | if resolvedURL.Scheme == "file" && cu.Scheme != "file" { 36 | return "", fmt.Errorf("cannot access file resources from network context") 37 | } 38 | resolvedURLString := resolvedURL.String() 39 | return resolvedURLString, nil 40 | } 41 | 42 | // IsLocalSchemaID validates if a given id is a local id 43 | func IsLocalSchemaID(id string) bool { 44 | splitID := strings.Split(id, "#") 45 | if len(splitID) > 1 && len(splitID[0]) > 0 && splitID[0][0] != '#' { 46 | return false 47 | } 48 | return id != "#" && !strings.HasPrefix(id, "#/") && strings.Contains(id, "#") 49 | } 50 | --------------------------------------------------------------------------------