├── test ├── JSON-Schema-Test-Suite │ ├── .gitignore │ ├── remotes │ │ ├── integer.json │ │ ├── folder │ │ │ └── folderInteger.json │ │ └── subSchemas.json │ ├── .travis.yml │ ├── tests │ │ ├── draft3 │ │ │ ├── optional │ │ │ │ ├── zeroTerminatedFloats.json │ │ │ │ ├── jsregex.json │ │ │ │ └── bignum.json │ │ │ ├── pattern.json │ │ │ ├── minItems.json │ │ │ ├── maxLength.json │ │ │ ├── minLength.json │ │ │ ├── maxItems.json │ │ │ ├── enum.json │ │ │ ├── maximum.json │ │ │ ├── minimum.json │ │ │ ├── items.json │ │ │ ├── required.json │ │ │ ├── divisibleBy.json │ │ │ ├── additionalProperties.json │ │ │ ├── refRemote.json │ │ │ ├── disallow.json │ │ │ ├── additionalItems.json │ │ │ ├── uniqueItems.json │ │ │ ├── extends.json │ │ │ ├── properties.json │ │ │ ├── dependencies.json │ │ │ ├── patternProperties.json │ │ │ └── ref.json │ │ └── draft4 │ │ │ ├── optional │ │ │ ├── zeroTerminatedFloats.json │ │ │ ├── bignum.json │ │ │ └── format.json │ │ │ ├── pattern.json │ │ │ ├── minItems.json │ │ │ ├── maxLength.json │ │ │ ├── minLength.json │ │ │ ├── maxItems.json │ │ │ ├── minProperties.json │ │ │ ├── maxProperties.json │ │ │ ├── definitions.json │ │ │ ├── required.json │ │ │ ├── enum.json │ │ │ ├── maximum.json │ │ │ ├── minimum.json │ │ │ ├── items.json │ │ │ ├── multipleOf.json │ │ │ ├── anyOf.json │ │ │ ├── oneOf.json │ │ │ ├── not.json │ │ │ ├── additionalProperties.json │ │ │ ├── refRemote.json │ │ │ ├── additionalItems.json │ │ │ ├── uniqueItems.json │ │ │ ├── properties.json │ │ │ ├── allOf.json │ │ │ ├── dependencies.json │ │ │ ├── patternProperties.json │ │ │ └── ref.json │ ├── LICENSE │ └── README.md ├── run.sh ├── invalid_schemas │ ├── maximum.json │ ├── minimum.json │ ├── cycle.json │ ├── ref.json │ ├── minItems.json │ ├── maxLength.json │ ├── minLength.json │ ├── pattern.json │ ├── items.json │ ├── uniqueItems.json │ ├── exclusiveMaximum.json │ ├── exclusiveMinimum.json │ ├── title.json │ ├── type.json │ ├── description.json │ ├── required.json │ ├── maxProperties.json │ ├── minProperties.json │ ├── freeFormProperty.json │ ├── not.json │ ├── patternProperties.json │ ├── properties.json │ ├── multipleOf.json │ ├── id.json │ ├── additionalProperties.json │ ├── definitions.json │ ├── allOf.json │ ├── anyOf.json │ ├── oneOf.json │ ├── enum.json │ └── dependencies.json ├── runner.dart ├── cover.dart ├── test_invalid_schemas.dart └── test_validation.dart ├── LICENSE ├── .travis.yml ├── dot_samples ├── draft04_schema.png ├── schemaout │ ├── card.png │ ├── crs.png │ ├── movies.png │ ├── geometry.png │ ├── json-home.png │ ├── avro-schema.png │ ├── json-patch.png │ ├── draft04_schema.png │ ├── movies.dot │ ├── card.dot │ └── crs.dot ├── README.md ├── schemas │ ├── movies.json │ ├── card.json │ ├── crs.json │ ├── json-patch.json │ ├── geometry.json │ ├── draft04_schema.json │ └── avro-schema.json └── original │ ├── crs.json │ ├── json-patch.json │ ├── geometry.json │ └── avro-schema.json ├── example ├── from_url │ ├── grades_schema.png │ ├── grades_schema.json │ └── validate_instance_from_url.dart └── from_json │ ├── validate_json_from_data.dart │ └── movie_sample.dart ├── COPYRIGHT_TRANSFER ├── CHANGELOG.md ├── .gitignore ├── tool └── travis.sh ├── pubspec.yaml ├── bin ├── gensamples.dart └── schemadot.dart ├── lib └── json_schema.dart └── README.md /test/JSON-Schema-Test-Suite/.gitignore: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/remotes/integer.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer" 3 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | License: Boost License 1.0. 2 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/remotes/folder/folderInteger.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer" 3 | } -------------------------------------------------------------------------------- /test/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | dart tool/hop_runner.dart analyze_lib 3 | dart test/runner.dart 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: dart 2 | sudo: false 3 | dart: 4 | - stable 5 | - dev 6 | script: ./tool/travis.sh -------------------------------------------------------------------------------- /dot_samples/draft04_schema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patefacio/json_schema/HEAD/dot_samples/draft04_schema.png -------------------------------------------------------------------------------- /dot_samples/schemaout/card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patefacio/json_schema/HEAD/dot_samples/schemaout/card.png -------------------------------------------------------------------------------- /dot_samples/schemaout/crs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patefacio/json_schema/HEAD/dot_samples/schemaout/crs.png -------------------------------------------------------------------------------- /dot_samples/schemaout/movies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patefacio/json_schema/HEAD/dot_samples/schemaout/movies.png -------------------------------------------------------------------------------- /dot_samples/schemaout/geometry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patefacio/json_schema/HEAD/dot_samples/schemaout/geometry.png -------------------------------------------------------------------------------- /dot_samples/schemaout/json-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patefacio/json_schema/HEAD/dot_samples/schemaout/json-home.png -------------------------------------------------------------------------------- /example/from_url/grades_schema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patefacio/json_schema/HEAD/example/from_url/grades_schema.png -------------------------------------------------------------------------------- /dot_samples/schemaout/avro-schema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patefacio/json_schema/HEAD/dot_samples/schemaout/avro-schema.png -------------------------------------------------------------------------------- /dot_samples/schemaout/json-patch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patefacio/json_schema/HEAD/dot_samples/schemaout/json-patch.png -------------------------------------------------------------------------------- /dot_samples/schemaout/draft04_schema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patefacio/json_schema/HEAD/dot_samples/schemaout/draft04_schema.png -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: "2.7" 3 | install: pip install jsonschema 4 | script: bin/jsonschema_suite check 5 | -------------------------------------------------------------------------------- /COPYRIGHT_TRANSFER: -------------------------------------------------------------------------------- 1 | I, Daniel Davidson, hereby assign the copyright of JSON Schema to Workiva Inc., to be carried forward under an open source license. 2 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/remotes/subSchemas.json: -------------------------------------------------------------------------------- 1 | { 2 | "integer": { 3 | "type": "integer" 4 | }, 5 | "refToInteger": { 6 | "$ref": "#/integer" 7 | } 8 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.7 2 | 3 | * Update dependency constraint on the `args` package. 4 | 5 | ## 1.0.3 6 | 7 | * Add a dependency on the `args` package. 8 | 9 | ## 1.0.2 10 | 11 | * Add a dependency on the `logging` package. 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.~*~ 2 | .packages 3 | packages 4 | build/ 5 | .pub/ 6 | .project 7 | *.iml 8 | *.ipr 9 | *.iws 10 | .idea/ 11 | *.dart.js 12 | *.js_ 13 | *.js.deps 14 | *.js.map 15 | # custom 16 | pubspec.lock 17 | # end 18 | 19 | -------------------------------------------------------------------------------- /test/invalid_schemas/maximum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "maximum: must be a JSON number, not a string", 4 | "schema" : { "maximum" : "foo" } 5 | }, 6 | { 7 | "description" : "maximum: must be a JSON number, not an array", 8 | "schema" : { "maximum" : [] } 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /test/invalid_schemas/minimum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "minimum: must be a JSON number, not a string", 4 | "schema" : { "minimum" : "foo" } 5 | }, 6 | { 7 | "description" : "minimum: must be a JSON number, not an array", 8 | "schema" : { "minimum" : [] } 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /test/invalid_schemas/cycle.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "schema can not have cycles", 4 | "schema" : { 5 | "definitions" : { 6 | "a" : { "$ref" : "#/definitions/b" }, 7 | "b" : { "$ref" : "#/definitions/a" } 8 | } 9 | } 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /dot_samples/README.md: -------------------------------------------------------------------------------- 1 | # Samples of Generated _Json Schema_ Pictures 2 | 3 | The _json schema_ in the *schemas* folder are used to generate the _dot files_ and the _png files_ in the *schemaout* folder by the _../bin/gensamples.dart_ script. To do similar you need Graphviz installed. Many of the sample schema came from [this schema repository](https://github.com/fge/sample-json-schemas). 4 | -------------------------------------------------------------------------------- /test/invalid_schemas/ref.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "ref: must be a string - not object", 4 | "schema" : { "$ref" : {} } 5 | }, 6 | { 7 | "description" : "ref: must be a string - not array", 8 | "schema" : { "$ref" : [] } 9 | }, 10 | { 11 | "description" : "ref: must be a string - not number", 12 | "schema" : { "$ref" : 3.14 } 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /tool/travis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Fast fail the script on failures. 4 | set -e 5 | 6 | # Skipping this until at least we have a dev release that aligns with dart_style version 7 | # $(dirname -- "$0")/ensure_dartfmt.sh 8 | 9 | # Run the tests. 10 | dart test/runner.dart 11 | 12 | # Run the build.dart file - just to make sure it works 13 | $(dirname $(readlink -f `which dart`))/dartanalyzer lib/*.dart test/*.dart 14 | 15 | -------------------------------------------------------------------------------- /test/invalid_schemas/minItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "minItems: must be an integer - not string", 4 | "schema" : { "minItems" : "foo" } 5 | }, 6 | { 7 | "description" : "minItems: must be an integer - not num", 8 | "schema" : { "minItems" : 1.5 } 9 | }, 10 | { 11 | "description" : "minItems: must be >= 0", 12 | "schema" : { "minItems" : -1 } 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /test/invalid_schemas/maxLength.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "maxLength: must be an integer - not string", 4 | "schema" : { "maxLength" : "foo" } 5 | }, 6 | { 7 | "description" : "maxLength: must be an integer - not num", 8 | "schema" : { "maxLength" : 1.5 } 9 | }, 10 | { 11 | "description" : "maxLength: must be >= 0", 12 | "schema" : { "maxLength" : -1 } 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /test/invalid_schemas/minLength.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "minLength: must be an integer - not string", 4 | "schema" : { "minLength" : "foo" } 5 | }, 6 | { 7 | "description" : "minLength: must be an integer - not num", 8 | "schema" : { "minLength" : 1.5 } 9 | }, 10 | { 11 | "description" : "minLength: must be >= 0", 12 | "schema" : { "minLength" : -1 } 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /test/invalid_schemas/pattern.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "pattern: must be a string - not object", 4 | "schema" : { "pattern" : {} } 5 | }, 6 | { 7 | "description" : "pattern: must be a string - not array", 8 | "schema" : { "pattern" : [] } 9 | }, 10 | { 11 | "description" : "pattern: must be a string - not number", 12 | "schema" : { "pattern" : 3.14 } 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /test/runner.dart: -------------------------------------------------------------------------------- 1 | import 'package:logging/logging.dart'; 2 | import 'test_invalid_schemas.dart' as test_invalid_schemas; 3 | import 'test_validation.dart' as test_validation; 4 | 5 | void main() { 6 | Logger.root.level = Level.OFF; 7 | Logger.root.onRecord.listen((LogRecord rec) { 8 | print('${rec.level.name}: ${rec.time}: ${rec.message}'); 9 | }); 10 | 11 | test_invalid_schemas.main(null); 12 | test_validation.main(null); 13 | } 14 | -------------------------------------------------------------------------------- /test/invalid_schemas/items.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "items: must be an array or object, not a string", 4 | "schema" : { "items" : "foo" } 5 | }, 6 | { 7 | "description" : "items: must be an array or object, not a int", 8 | "schema" : { "items" : 42 } 9 | }, 10 | { 11 | "description" : "items: must be an array or object, not a num", 12 | "schema" : { "items" : 3.14 } 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /test/invalid_schemas/uniqueItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "uniqueItems: must be a boolean - not a string", 4 | "schema" : { "uniqueItems" : "foo" } 5 | }, 6 | { 7 | "description" : "uniqueItems: must be a boolean - not an array ", 8 | "schema" : { "maximum" : [] } 9 | }, 10 | { 11 | "description" : "uniqueItems: must be a boolean - not an object ", 12 | "schema" : { "maximum" : {} } 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /test/invalid_schemas/exclusiveMaximum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "exclusiveMaximum: must be a boolean", 4 | "schema" : { "maximum" : 3, "exclusiveMaximum" : "foo" } 5 | }, 6 | { 7 | "description" : "exclusiveMaximum: requires maximum if true", 8 | "schema" : { "exclusiveMaximum" : true } 9 | }, 10 | { 11 | "description" : "exclusiveMaximum: requires maximum if false", 12 | "schema" : { "exclusiveMaximum" : false } 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /test/invalid_schemas/exclusiveMinimum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "exclusiveMinimum: must be a boolean", 4 | "schema" : { "minimum" : 3, "exclusiveMinimum" : "foo" } 5 | }, 6 | { 7 | "description" : "exclusiveMinimum: requires minimum if true", 8 | "schema" : { "exclusiveMinimum" : true } 9 | }, 10 | { 11 | "description" : "exclusiveMinimum: requires minimum if false", 12 | "schema" : { "exclusiveMinimum" : false } 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /test/invalid_schemas/title.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "title: must be a string - not object", 4 | "schema" : { "title" : {} } 5 | }, 6 | { 7 | "description" : "title: must be a string - not array", 8 | "schema" : { "title" : [] } 9 | }, 10 | { 11 | "description" : "title: must be a string - not int", 12 | "schema" : { "title" : 3 } 13 | }, 14 | { 15 | "description" : "title: must be a string - not number", 16 | "schema" : { "title" : 3.14 } 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /test/invalid_schemas/type.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "type: must be 'string' or 'array', not integer", 4 | "schema" : { "type" : 3 } 5 | }, 6 | { 7 | "description" : "type: must be 'string' or 'array', not object", 8 | "schema" : { "type" : {} } 9 | }, 10 | { 11 | "description" : "type: should be integer, not int", 12 | "schema" : { "type" : "int" } 13 | }, 14 | { 15 | "description" : "type: sould be boolean not bool", 16 | "schema" : { "type" : ["bool"] } 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft3/optional/jsregex.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 | -------------------------------------------------------------------------------- /test/invalid_schemas/description.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "description: must be a string - not object", 4 | "schema" : { "description" : {} } 5 | }, 6 | { 7 | "description" : "description: must be a string - not array", 8 | "schema" : { "description" : [] } 9 | }, 10 | { 11 | "description" : "description: must be a string - not int", 12 | "schema" : { "description" : 3 } 13 | }, 14 | { 15 | "description" : "description: must be a string - not number", 16 | "schema" : { "description" : 3.14 } 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /test/invalid_schemas/required.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "required: must be non-empty array, not a string ", 4 | "schema" : { "required" : "foo" } 5 | }, 6 | { 7 | "description" : "required: must be non-empty array, not an object", 8 | "schema" : { "required" : {} } 9 | }, 10 | { 11 | "description" : "required: must be non-empty array, not an int", 12 | "schema" : { "required" : 3 } 13 | }, 14 | { 15 | "description" : "required: must be non-empty array", 16 | "schema" : { "required" : [] } 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /test/invalid_schemas/maxProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "maxProperties: must be a non-negative int - not string", 4 | "schema" : { "maxProperties" : "foo" } 5 | }, 6 | { 7 | "description" : "maxProperties: must be a non-negative int - not object", 8 | "schema" : { "maxProperties" : {} } 9 | }, 10 | { 11 | "description" : "maxProperties: must be a non-negative int - not array", 12 | "schema" : { "maxProperties" : [] } 13 | }, 14 | { 15 | "description" : "maxProperties: must be a non-negative int - not num", 16 | "schema" : { "maxProperties" : 3.14 } 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /test/invalid_schemas/minProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "minProperties: must be a non-negative int - not string", 4 | "schema" : { "minProperties" : "foo" } 5 | }, 6 | { 7 | "description" : "minProperties: must be a non-negative int - not object", 8 | "schema" : { "minProperties" : {} } 9 | }, 10 | { 11 | "description" : "minProperties: must be a non-negative int - not array", 12 | "schema" : { "minProperties" : [] } 13 | }, 14 | { 15 | "description" : "minProperties: must be a non-negative int - not num", 16 | "schema" : { "minProperties" : 3.14 } 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /test/invalid_schemas/freeFormProperty.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "referenced non-keyword property must be valid schema - not array", 4 | "schema" : { 5 | "foo" : [], 6 | "properties" : { 7 | "goo" : { "$ref" : "#/foo" } 8 | } 9 | } 10 | }, 11 | { 12 | "description" : "referenced non-keyword property must be valid schema - invalid schema", 13 | "schema" : { 14 | "foo" : { 15 | "type" : "foo" 16 | }, 17 | "properties" : { 18 | "goo" : { "$ref" : "#/foo" } 19 | } 20 | } 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /test/invalid_schemas/not.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "not: must be an object - not string", 4 | "schema" : { "not" : "foo" } 5 | }, 6 | { 7 | "description" : "not: must be an object - not int", 8 | "schema" : { "not" : 42 } 9 | }, 10 | { 11 | "description" : "not: must be an object - not num", 12 | "schema" : { "not" : 3.14 } 13 | }, 14 | { 15 | "description" : "not: must be an object - not num", 16 | "schema" : { "not" : [] } 17 | }, 18 | { 19 | "description" : "not: object must valid schema", 20 | "schema" : { 21 | "not" : { 22 | "minimum" : "foo" 23 | } 24 | } 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /test/invalid_schemas/patternProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "patternProperties: must be an object - not array", 4 | "schema" : { "patternProperties" : [] } 5 | }, 6 | { 7 | "description" : "patternProperties: must be an object - not int", 8 | "schema" : { "patternProperties" : 3 } 9 | }, 10 | { 11 | "description" : "patternProperties: must be an object - not number", 12 | "schema" : { "patternProperties" : 3.14 } 13 | }, 14 | { 15 | "description" : "patternProperties: must be an object and each value must be valid schema", 16 | "schema" : { 17 | "patternProperties" : { 18 | "foo" : [] 19 | } 20 | } 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /dot_samples/schemas/movies.json: -------------------------------------------------------------------------------- 1 | { 2 | "title" : "movie data", 3 | "additionalProperties" : false, 4 | "required" : [ "movies" ], 5 | "properties" : { 6 | "movies" : { "$ref" : "#/definitions/movie_map" } 7 | }, 8 | "definitions" : { 9 | "movie" : { 10 | "additionalProperties": false, 11 | "required" : [ "title", "year_made", "rating" ], 12 | "properties": { 13 | "title" : { "type" : "string" }, 14 | "year_made" : { "type" : "integer" }, 15 | "rating" : { "type" : "integer" } 16 | } 17 | }, 18 | "movie_map" : { 19 | "type": "object", 20 | "additionalProperties": { "$ref": "#/definitions/movie" }, 21 | "default": {} 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/invalid_schemas/properties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "properties: must be an object", 4 | "schema" : { "properties" : "foo" } 5 | }, 6 | { 7 | "description" : "properties: must be an object", 8 | "schema" : { "properties" : 3 } 9 | }, 10 | { 11 | "description" : "properties: must be an object", 12 | "schema" : { "properties" : 3.14 } 13 | }, 14 | { 15 | "description" : "properties: must be an object", 16 | "schema" : { "properties" : [] } 17 | }, 18 | { 19 | "description" : "properties: must be an object where values are schemas", 20 | "schema" : { 21 | "properties" : { 22 | "foo" : [] 23 | } 24 | } 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | } 28 | ] 29 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | } 28 | ] 29 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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": 10, 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | } 28 | ] 29 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /test/invalid_schemas/multipleOf.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "multipleOf: must be 'num', not a 'string'", 4 | "schema" : { "multipleOf" : "foo" } 5 | }, 6 | { 7 | "description" : "multipleOf: must be 'num', not a 'array'", 8 | "schema" : { "multipleOf" : [] } 9 | }, 10 | { 11 | "description" : "multipleOf: must be 'num' greater than 0", 12 | "schema" : { "multipleOf" : 0 } 13 | }, 14 | { 15 | "description" : "multipleOf: must be 'num' greater than 0.0", 16 | "schema" : { "multipleOf" : 0.0 } 17 | }, 18 | { 19 | "description" : "multipleOf: must be 'num' greater than 0", 20 | "schema" : { "multipleOf" : -1 } 21 | }, 22 | { 23 | "description" : "multipleOf: must be 'num' greater than 0", 24 | "schema" : { "multipleOf" : -1.5 } 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 non-objects", 23 | "data": "", 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /test/invalid_schemas/id.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "id must be a string - not int", 4 | "schema" : { "id" : 1 } 5 | }, 6 | { 7 | "description" : "id must be a string - not object", 8 | "schema" : { "id" : {} } 9 | }, 10 | { 11 | "description" : "id must be a string - not array", 12 | "schema" : { "id" : [] } 13 | }, 14 | { 15 | "description" : "id must be a string - not int", 16 | "schema" : { "id" : 3 } 17 | }, 18 | { 19 | "description" : "id must be a string - not num", 20 | "schema" : { "id" : 3.14 } 21 | }, 22 | { 23 | "description" : "id must be a valid URI", 24 | "schema" : { "id" : "127.0.0.1:0xfff" } 25 | }, 26 | { 27 | "description" : "id must be a valid URI", 28 | "schema" : { "id" : "http://localhost:^" } 29 | } 30 | ] 31 | -------------------------------------------------------------------------------- /test/invalid_schemas/additionalProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "additionalProperties: must be a boolean or object - not string", 4 | "schema" : { "additionalProperties" : "foo" } 5 | }, 6 | { 7 | "description" : "additionalProperties: must be a boolean or object - not int", 8 | "schema" : { "additionalProperties" : 3 } 9 | }, 10 | { 11 | "description" : "additionalProperties: must be a boolean or object - not number", 12 | "schema" : { "additionalProperties" : 3.14 } 13 | }, 14 | { 15 | "description" : "additionalProperties: must be a boolean or object - not array", 16 | "schema" : { "additionalProperties" : [] } 17 | }, 18 | { 19 | "description" : "additionalProperties: if object must be valid json schema", 20 | "schema" : { 21 | "additionalProperties" : [] 22 | } 23 | } 24 | ] 25 | -------------------------------------------------------------------------------- /test/invalid_schemas/definitions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "definitions: must be an object - not string", 4 | "schema" : { "definitions" : "foo" } 5 | }, 6 | { 7 | "description" : "definitions: must be an object - not int", 8 | "schema" : { "definitions" : 3 } 9 | }, 10 | { 11 | "description" : "definitions: must be an object - not num", 12 | "schema" : { "definitions" : 3.14 } 13 | }, 14 | { 15 | "description" : "definitions: must be an object - not array", 16 | "schema" : { "definitions" : [] } 17 | }, 18 | { 19 | "description" : "definitions: must be an object and each value must be valid schema", 20 | "schema" : { 21 | "definitions" : { 22 | "definition_1" : { 23 | "minimum" : "goo" 24 | } 25 | } 26 | } 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 non-objects", 23 | "data": "foobar", 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: json_schema 2 | version: 1.0.7 3 | author: Daniel Davidson 4 | homepage: https://github.com/patefacio/json_schema 5 | description: > 6 | Provide support for validating instances against json schema 7 | environment: 8 | sdk: '>=1.8.2 <2.0.0' 9 | 10 | dependencies: 11 | 12 | # custom 13 | 14 | path: "^1.3.0" 15 | logging: ">=0.9.3<0.12.0" 16 | args: ">=0.11.0 <2.0.0" 17 | 18 | # end 19 | 20 | dev_dependencies: 21 | 22 | # custom 23 | 24 | test: "^0.12.13" 25 | yaml: "^2.1.0" 26 | coverage: ">=0.7.6" 27 | 28 | # end 29 | 30 | dependency_overrides: 31 | # custom 32 | 33 | # end 34 | 35 | transformers: 36 | 37 | # custom 38 | # end 39 | 40 | -------------------------------------------------------------------------------- /example/from_json/validate_json_from_data.dart: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env dart 2 | 3 | import "package:json_schema/json_schema.dart"; 4 | import "package:logging/logging.dart"; 5 | 6 | main() { 7 | 8 | Logger.root.onRecord.listen((LogRecord rec) => 9 | print('${rec.level.name}: ${rec.time}: ${rec.message}')); 10 | Logger.root.level = Level.SHOUT; 11 | 12 | ////////////////////////////////////////////////////////////////////// 13 | // Define schema in code 14 | ////////////////////////////////////////////////////////////////////// 15 | var mustBeIntegerSchema = { 16 | "type" : "integer" 17 | }; 18 | 19 | var n = 3; 20 | var decimals = 3.14; 21 | var str = 'hi'; 22 | 23 | Schema.createSchema(mustBeIntegerSchema) 24 | .then((schema) { 25 | print('$n => ${schema.validate(n)}'); 26 | print('$decimals => ${schema.validate(decimals)}'); 27 | print('$str => ${schema.validate(str)}'); 28 | }); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /test/invalid_schemas/allOf.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "allOf: must be an array - not string", 4 | "schema" : { "allOf" : "foo" } 5 | }, 6 | { 7 | "description" : "allOf: must be an array - not int", 8 | "schema" : { "allOf" : 42 } 9 | }, 10 | { 11 | "description" : "allOf: must be an array - not num", 12 | "schema" : { "allOf" : 3.14 } 13 | }, 14 | { 15 | "description" : "allOf: must be an array - not object", 16 | "schema" : { "allOf" : {} } 17 | }, 18 | { 19 | "description" : "allOf: must be a non-empty array", 20 | "schema" : { "allOf" : [] } 21 | }, 22 | { 23 | "description" : "allOf: elements must be valid schemas", 24 | "schema" : { 25 | "allOf" : [ 26 | { 27 | "minimum" : "foo" 28 | } 29 | ] 30 | } 31 | } 32 | ] 33 | -------------------------------------------------------------------------------- /test/invalid_schemas/anyOf.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "anyOf: must be an array - not string", 4 | "schema" : { "anyOf" : "foo" } 5 | }, 6 | { 7 | "description" : "anyOf: must be an array - not int", 8 | "schema" : { "anyOf" : 42 } 9 | }, 10 | { 11 | "description" : "anyOf: must be an array - not num", 12 | "schema" : { "anyOf" : 3.14 } 13 | }, 14 | { 15 | "description" : "anyOf: must be an array - not object", 16 | "schema" : { "anyOf" : {} } 17 | }, 18 | { 19 | "description" : "anyOf: must be a non-empty array", 20 | "schema" : { "anyOf" : [] } 21 | }, 22 | { 23 | "description" : "anyOf: elements must be valid schemas", 24 | "schema" : { 25 | "anyOf" : [ 26 | { 27 | "minimum" : "foo" 28 | } 29 | ] 30 | } 31 | } 32 | ] 33 | -------------------------------------------------------------------------------- /test/invalid_schemas/oneOf.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "oneOf: must be an array - not string", 4 | "schema" : { "oneOf" : "foo" } 5 | }, 6 | { 7 | "description" : "oneOf: must be an array - not int", 8 | "schema" : { "oneOf" : 42 } 9 | }, 10 | { 11 | "description" : "oneOf: must be an array - not num", 12 | "schema" : { "oneOf" : 3.14 } 13 | }, 14 | { 15 | "description" : "oneOf: must be an array - not object", 16 | "schema" : { "oneOf" : {} } 17 | }, 18 | { 19 | "description" : "oneOf: must be a non-empty array", 20 | "schema" : { "oneOf" : [] } 21 | }, 22 | { 23 | "description" : "oneOf: elements must be valid schemas", 24 | "schema" : { 25 | "oneOf" : [ 26 | { 27 | "minimum" : "foo" 28 | } 29 | ] 30 | } 31 | } 32 | ] 33 | -------------------------------------------------------------------------------- /test/cover.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'package:logging/logging.dart'; 3 | import 'package:coverage/coverage.dart'; 4 | import 'runner.dart' as runner; 5 | import 'package:path/path.dart'; 6 | 7 | 8 | main() async { 9 | Logger.root.level = Level.OFF; 10 | Logger.root.onRecord.listen((LogRecord rec) { 11 | print('${rec.level.name}: ${rec.time}: ${rec.message}'); 12 | }); 13 | 14 | final results = await runAndCollect('runner.dart'); 15 | 16 | final untested = {}; 17 | results['coverage'].forEach((var entry) { 18 | final source = entry['source']; 19 | if(!source.contains('package:json_schema')) return; 20 | print(source); 21 | final hits = entry['hits']; 22 | final hitCount = hits.length/2; 23 | for(int i=0; i []).add(lineNumber); 28 | } 29 | } 30 | }); 31 | 32 | print(untested); 33 | } 34 | -------------------------------------------------------------------------------- /test/invalid_schemas/enum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "enum: must be an array - not string", 4 | "schema" : { "enum" : "foo" } 5 | }, 6 | { 7 | "description" : "enum: must be an array - not int", 8 | "schema" : { "enum" : 42 } 9 | }, 10 | { 11 | "description" : "enum: must be an array - not num", 12 | "schema" : { "enum" : 3.14 } 13 | }, 14 | { 15 | "description" : "enum: must be an array - not object", 16 | "schema" : { "enum" : {} } 17 | }, 18 | { 19 | "description" : "enum: must be a non-empty array", 20 | "schema" : { "enum" : [] } 21 | }, 22 | { 23 | "description" : "enum: elements must be unique", 24 | "schema" : { "enum" : [3,4,3] } 25 | }, 26 | { 27 | "description" : "enum: elements must be deeply unique", 28 | "schema" : { "enum" : [ 29 | {"c":"d", "a":"b"}, 30 | 4, 31 | {"a":"b", "c":"d"} 32 | ] } 33 | } 34 | ] 35 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | }, 24 | { 25 | "description": "required default validation", 26 | "schema": { 27 | "properties": { 28 | "foo": {} 29 | } 30 | }, 31 | "tests": [ 32 | { 33 | "description": "not required by default", 34 | "data": {}, 35 | "valid": true 36 | } 37 | ] 38 | } 39 | ] 40 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Julian Berman 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /bin/gensamples.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'package:path/path.dart'; 3 | import 'package:json_schema/json_schema.dart'; 4 | import 'package:json_schema/schema_dot.dart'; 5 | 6 | main() { 7 | var sourcePath = join(dirname(dirname(absolute(Platform.script.toFilePath()))), 8 | 'dot_samples', 'schemas'); 9 | var outPath = join(dirname(sourcePath), 'schemaout'); 10 | new Directory(sourcePath).listSync().forEach((jsonFile) { 11 | var fname = jsonFile.path; 12 | var base = basenameWithoutExtension(fname); 13 | var dotFilename = join(outPath, '$base.dot'); 14 | var pngOut = join(outPath, '$base.png'); 15 | 16 | Schema.createSchemaFromUrl(fname) 17 | .then((schema) { 18 | new File(dotFilename).writeAsStringSync(createDot(schema)); 19 | }) 20 | .then((_) { 21 | 22 | Process.run('dot', ['-Tpng', '-o$pngOut', dotFilename]) 23 | .then((ProcessResult processResult) { 24 | if(processResult.exitCode == 0) { 25 | print("Finished running dot -Tpng -o$pngOut $fname"); 26 | } else { 27 | print("FAILED: running dot -Tpng -o$pngOut $fname"); 28 | } 29 | }); 30 | }); 31 | }); 32 | } -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft4/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 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft3/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": "above the maximum is invalid", 13 | "data": 3.5, 14 | "valid": false 15 | }, 16 | { 17 | "description": "ignores non-numbers", 18 | "data": "x", 19 | "valid": true 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "exclusiveMaximum validation", 25 | "schema": { 26 | "maximum": 3.0, 27 | "exclusiveMaximum": true 28 | }, 29 | "tests": [ 30 | { 31 | "description": "below the maximum is still valid", 32 | "data": 2.2, 33 | "valid": true 34 | }, 35 | { 36 | "description": "boundary point is invalid", 37 | "data": 3.0, 38 | "valid": false 39 | } 40 | ] 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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": "below the minimum is invalid", 13 | "data": 0.6, 14 | "valid": false 15 | }, 16 | { 17 | "description": "ignores non-numbers", 18 | "data": "x", 19 | "valid": true 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "exclusiveMinimum validation", 25 | "schema": { 26 | "minimum": 1.1, 27 | "exclusiveMinimum": true 28 | }, 29 | "tests": [ 30 | { 31 | "description": "above the minimum is still valid", 32 | "data": 1.2, 33 | "valid": true 34 | }, 35 | { 36 | "description": "boundary point is invalid", 37 | "data": 1.1, 38 | "valid": false 39 | } 40 | ] 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft4/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": "above the maximum is invalid", 13 | "data": 3.5, 14 | "valid": false 15 | }, 16 | { 17 | "description": "ignores non-numbers", 18 | "data": "x", 19 | "valid": true 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "exclusiveMaximum validation", 25 | "schema": { 26 | "maximum": 3.0, 27 | "exclusiveMaximum": true 28 | }, 29 | "tests": [ 30 | { 31 | "description": "below the maximum is still valid", 32 | "data": 2.2, 33 | "valid": true 34 | }, 35 | { 36 | "description": "boundary point is invalid", 37 | "data": 3.0, 38 | "valid": false 39 | } 40 | ] 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft4/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": "below the minimum is invalid", 13 | "data": 0.6, 14 | "valid": false 15 | }, 16 | { 17 | "description": "ignores non-numbers", 18 | "data": "x", 19 | "valid": true 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "exclusiveMinimum validation", 25 | "schema": { 26 | "minimum": 1.1, 27 | "exclusiveMinimum": true 28 | }, 29 | "tests": [ 30 | { 31 | "description": "above the minimum is still valid", 32 | "data": 1.2, 33 | "valid": true 34 | }, 35 | { 36 | "description": "boundary point is invalid", 37 | "data": 1.1, 38 | "valid": false 39 | } 40 | ] 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft4/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 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft3/optional/bignum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "integer", 4 | "schema": {"type": "integer"}, 5 | "tests": [ 6 | { 7 | "description": "a bignum is an integer", 8 | "data": 12345678910111213141516171819202122232425262728293031, 9 | "valid": true 10 | } 11 | ] 12 | }, 13 | { 14 | "description": "number", 15 | "schema": {"type": "number"}, 16 | "tests": [ 17 | { 18 | "description": "a bignum is a number", 19 | "data": 98249283749234923498293171823948729348710298301928331, 20 | "valid": true 21 | } 22 | ] 23 | }, 24 | { 25 | "description": "string", 26 | "schema": {"type": "string"}, 27 | "tests": [ 28 | { 29 | "description": "a bignum is not a string", 30 | "data": 98249283749234923498293171823948729348710298301928331, 31 | "valid": false 32 | } 33 | ] 34 | }, 35 | { 36 | "description": "float comparison with high precision", 37 | "schema": { 38 | "maximum": 972783798187987123879878123.18878137, 39 | "exclusiveMaximum": true 40 | }, 41 | "tests": [ 42 | { 43 | "description": "comparison works for high numbers", 44 | "data": 972783798187987123879878123.188781371, 45 | "valid": false 46 | } 47 | ] 48 | } 49 | ] 50 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft4/optional/bignum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "integer", 4 | "schema": {"type": "integer"}, 5 | "tests": [ 6 | { 7 | "description": "a bignum is an integer", 8 | "data": 12345678910111213141516171819202122232425262728293031, 9 | "valid": true 10 | } 11 | ] 12 | }, 13 | { 14 | "description": "number", 15 | "schema": {"type": "number"}, 16 | "tests": [ 17 | { 18 | "description": "a bignum is a number", 19 | "data": 98249283749234923498293171823948729348710298301928331, 20 | "valid": true 21 | } 22 | ] 23 | }, 24 | { 25 | "description": "string", 26 | "schema": {"type": "string"}, 27 | "tests": [ 28 | { 29 | "description": "a bignum is not a string", 30 | "data": 98249283749234923498293171823948729348710298301928331, 31 | "valid": false 32 | } 33 | ] 34 | }, 35 | { 36 | "description": "float comparison with high precision", 37 | "schema": { 38 | "maximum": 972783798187987123879878123.18878137, 39 | "exclusiveMaximum": true 40 | }, 41 | "tests": [ 42 | { 43 | "description": "comparison works for high numbers", 44 | "data": 972783798187987123879878123.188781371, 45 | "valid": false 46 | } 47 | ] 48 | } 49 | ] 50 | -------------------------------------------------------------------------------- /test/invalid_schemas/dependencies.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "dependencies: must be an object - not string", 4 | "schema" : { "dependencies" : "foo" } 5 | }, 6 | { 7 | "description" : "dependencies: must be an object - not int", 8 | "schema" : { "dependencies" : 3 } 9 | }, 10 | { 11 | "description" : "dependencies: must be an object - not num", 12 | "schema" : { "dependencies" : 3.14 } 13 | }, 14 | { 15 | "description" : "dependencies: must be an object - not array", 16 | "schema" : { "dependencies" : [] } 17 | }, 18 | { 19 | "description" : "dependencies: property dependencies non-empty array", 20 | "schema" : { 21 | "dependencies" : { 22 | "p1" : [] 23 | } 24 | } 25 | }, 26 | { 27 | "description" : "dependencies: values must be object (schema) or array", 28 | "schema" : { 29 | "dependencies" : { 30 | "p1" : "goo" 31 | } 32 | } 33 | }, 34 | { 35 | "description" : "dependencies: property dependencies must be strings", 36 | "schema" : { 37 | "dependencies" : { 38 | "p1" : [ 1 ] 39 | } 40 | } 41 | }, 42 | { 43 | "description" : "dependencies: property dependencies must be strings with no dupes", 44 | "schema" : { 45 | "dependencies" : { 46 | "p1" : [ "a", "b", "a" ] 47 | } 48 | } 49 | }, 50 | { 51 | "description" : "dependencies: schema dependencies must be valid schema", 52 | "schema" : { 53 | "dependencies" : { 54 | "p1" : { "minimum" : "oops" } 55 | } 56 | } 57 | } 58 | ] 59 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /example/from_url/grades_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title" : "Grade Tracker", 4 | "type" : "object", 5 | "additionalProperties" : false, 6 | "properties" : { 7 | "semesters" : { 8 | "type" : "array", 9 | "items" : { 10 | "type" : "object", 11 | "additionalProperties" : false, 12 | "properties" : { 13 | "semester": { "type" : "integer" }, 14 | "grades" : { 15 | "type" : "array", 16 | "items" : { 17 | "type" : "object", 18 | "additionalProperties" : false, 19 | "required" : [ "date", "type", "grade", "std" ], 20 | "properties" : { 21 | "date" : { "type" : "string"}, 22 | "type" : { "enum" : [ "homework", "quiz", "test", "final_exam" ] }, 23 | "grade" : { "type" : "number"}, 24 | "std" : { 25 | "oneOf" : [ 26 | {"type" : "number"}, 27 | {"type" : "null"} 28 | ] 29 | }, 30 | "avg" : { 31 | "oneOf" : [ 32 | {"type" : "number"}, 33 | {"type" : "null"} 34 | ] 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /dot_samples/schemas/card.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "description": "A representation of a person, company, organization, or place", 4 | "type": "object", 5 | "required": [ "familyName", "givenName" ], 6 | "properties": { 7 | "fn": { 8 | "description": "Formatted Name", 9 | "type": "string" 10 | }, 11 | "familyName": { "type": "string" }, 12 | "givenName": { "type": "string" }, 13 | "additionalName": { "type": "array", "items": { "type": "string" } }, 14 | "honorificPrefix": { "type": "array", "items": { "type": "string" } }, 15 | "honorificSuffix": { "type": "array", "items": { "type": "string" } }, 16 | "nickname": { "type": "string" }, 17 | "url": { "type": "string", "format": "uri" }, 18 | "email": { 19 | "type": "object", 20 | "properties": { 21 | "type": { "type": "string" }, 22 | "value": { "type": "string", "format": "email" } 23 | } 24 | }, 25 | "tel": { 26 | "type": "object", 27 | "properties": { 28 | "type": { "type": "string" }, 29 | "value": { "type": "string", "format": "phone" } 30 | } 31 | }, 32 | "tz": { "type": "string" }, 33 | "photo": { "type": "string" }, 34 | "logo": { "type": "string" }, 35 | "sound": { "type": "string" }, 36 | "bday": { "type": "string", "format": "date" }, 37 | "title": { "type": "string" }, 38 | "role": { "type": "string" }, 39 | "org": { 40 | "type": "object", 41 | "properties": { 42 | "organizationName": { "type": "string" }, 43 | "organizationUnit": { "type": "string" } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /dot_samples/original/crs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title": "crs", 4 | "description": "a Coordinate Reference System object", 5 | "type": [ "object", "null" ], 6 | "required": [ "type", "properties" ], 7 | "properties": { 8 | "type": { "type": "string" }, 9 | "properties": { "type": "object" } 10 | }, 11 | "additionalProperties": false, 12 | "oneOf": [ 13 | { "$ref": "#/definitions/namedCrs" }, 14 | { "$ref": "#/definitions/linkedCrs" } 15 | ], 16 | "definitions": { 17 | "namedCrs": { 18 | "properties": { 19 | "type": { "enum": [ "name" ] }, 20 | "properties": { 21 | "required": [ "name" ], 22 | "additionalProperties": false, 23 | "properties": { 24 | "name": { 25 | "type": "string", 26 | "FIXME": "semantic validation necessary" 27 | } 28 | } 29 | } 30 | } 31 | }, 32 | "linkObject": { 33 | "type": "object", 34 | "required": [ "href" ], 35 | "properties": { 36 | "href": { 37 | "type": "string", 38 | "format": "uri", 39 | "FIXME": "spec says \"dereferenceable\", cannot enforce that" 40 | }, 41 | "type": { 42 | "type": "string", 43 | "description": "Suggested values: proj4, ogjwkt, esriwkt" 44 | } 45 | } 46 | }, 47 | "linkedCRS": { 48 | "properties": { 49 | "type": { "enum": [ "link" ] }, 50 | "properties": { "$ref": "#/definitions/linkedObject" } 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /dot_samples/schemas/crs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title": "crs", 4 | "description": "a Coordinate Reference System object", 5 | "type": [ "object", "null" ], 6 | "required": [ "type", "properties" ], 7 | "properties": { 8 | "type": { "type": "string" }, 9 | "properties": { "type": "object" } 10 | }, 11 | "additionalProperties": false, 12 | "oneOf": [ 13 | { "$ref": "#/definitions/namedCrs" }, 14 | { "$ref": "#/definitions/linkedCrs" } 15 | ], 16 | "definitions": { 17 | "namedCrs": { 18 | "properties": { 19 | "type": { "enum": [ "name" ] }, 20 | "properties": { 21 | "required": [ "name" ], 22 | "additionalProperties": false, 23 | "properties": { 24 | "name": { 25 | "type": "string", 26 | "FIXME": "semantic validation necessary" 27 | } 28 | } 29 | } 30 | } 31 | }, 32 | "linkedObject": { 33 | "type": "object", 34 | "required": [ "href" ], 35 | "properties": { 36 | "href": { 37 | "type": "string", 38 | "format": "uri", 39 | "FIXME": "spec says \"dereferenceable\", cannot enforce that" 40 | }, 41 | "type": { 42 | "type": "string", 43 | "description": "Suggested values: proj4, ogjwkt, esriwkt" 44 | } 45 | } 46 | }, 47 | "linkedCrs": { 48 | "properties": { 49 | "type": { "enum": [ "link" ] }, 50 | "properties": { "$ref": "#/definitions/linkedObject" } 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft4/anyOf.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "anyOf", 4 | "schema": { 5 | "anyOf": [ 6 | { 7 | "type": "integer" 8 | }, 9 | { 10 | "minimum": 2 11 | } 12 | ] 13 | }, 14 | "tests": [ 15 | { 16 | "description": "first anyOf valid", 17 | "data": 1, 18 | "valid": true 19 | }, 20 | { 21 | "description": "second anyOf valid", 22 | "data": 2.5, 23 | "valid": true 24 | }, 25 | { 26 | "description": "both anyOf valid", 27 | "data": 3, 28 | "valid": true 29 | }, 30 | { 31 | "description": "neither anyOf valid", 32 | "data": 1.5, 33 | "valid": false 34 | } 35 | ] 36 | }, 37 | { 38 | "description": "anyOf with base schema", 39 | "schema": { 40 | "type": "string", 41 | "anyOf" : [ 42 | { 43 | "maxLength": 2 44 | }, 45 | { 46 | "minLength": 4 47 | } 48 | ] 49 | }, 50 | "tests": [ 51 | { 52 | "description": "mismatch base schema", 53 | "data": 3, 54 | "valid": false 55 | }, 56 | { 57 | "description": "one anyOf valid", 58 | "data": "foobar", 59 | "valid": true 60 | }, 61 | { 62 | "description": "both anyOf invalid", 63 | "data": "foo", 64 | "valid": false 65 | } 66 | ] 67 | } 68 | ] 69 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft4/oneOf.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "oneOf", 4 | "schema": { 5 | "oneOf": [ 6 | { 7 | "type": "integer" 8 | }, 9 | { 10 | "minimum": 2 11 | } 12 | ] 13 | }, 14 | "tests": [ 15 | { 16 | "description": "first oneOf valid", 17 | "data": 1, 18 | "valid": true 19 | }, 20 | { 21 | "description": "second oneOf valid", 22 | "data": 2.5, 23 | "valid": true 24 | }, 25 | { 26 | "description": "both oneOf valid", 27 | "data": 3, 28 | "valid": false 29 | }, 30 | { 31 | "description": "neither oneOf valid", 32 | "data": 1.5, 33 | "valid": false 34 | } 35 | ] 36 | }, 37 | { 38 | "description": "oneOf with base schema", 39 | "schema": { 40 | "type": "string", 41 | "oneOf" : [ 42 | { 43 | "minLength": 2 44 | }, 45 | { 46 | "maxLength": 4 47 | } 48 | ] 49 | }, 50 | "tests": [ 51 | { 52 | "description": "mismatch base schema", 53 | "data": 3, 54 | "valid": false 55 | }, 56 | { 57 | "description": "one oneOf valid", 58 | "data": "foobar", 59 | "valid": true 60 | }, 61 | { 62 | "description": "both oneOf valid", 63 | "data": "foo", 64 | "valid": false 65 | } 66 | ] 67 | } 68 | ] 69 | -------------------------------------------------------------------------------- /example/from_json/movie_sample.dart: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env dart 2 | 3 | import "package:json_schema/json_schema.dart"; 4 | import "package:logging/logging.dart"; 5 | 6 | main() { 7 | Logger.root.onRecord.listen((LogRecord rec) { 8 | print('${rec.level.name}: ${rec.time}: ${rec.message}'); 9 | }); 10 | Logger.root.level = Level.SHOUT; 11 | 12 | ////////////////////////////////////////////////////////////////////// 13 | // Define schema in code 14 | ////////////////////////////////////////////////////////////////////// 15 | var movieSchema = { 16 | "title" : "movie data", 17 | "additionalProperties" : false, 18 | "required" : [ "movies" ], 19 | "properties" : { 20 | "movies" : { r"$ref" : "#/definitions/movie_map" } 21 | }, 22 | "definitions" : { 23 | "movie" : { 24 | "additionalProperties": false, 25 | "required" : [ "title", "year_made", "rating" ], 26 | "properties": { 27 | "title" : { "type" : "string" }, 28 | "year_made" : { "type" : "integer" }, 29 | "rating" : { "type" : "integer" } 30 | } 31 | }, 32 | "movie_map" : { 33 | "type": "object", 34 | "additionalProperties": { r"$ref": "#/definitions/movie" }, 35 | "default": {} 36 | } 37 | } 38 | }; 39 | 40 | var movies = { 41 | "movies" : { 42 | "the mission" : { 43 | "title":"The Mission", 44 | "year_made":1986, 45 | "rating":5 46 | }, 47 | "troll 2" : { 48 | "title":"Troll 2", 49 | "year_made":1990, 50 | "rating":2 51 | } 52 | } 53 | }; 54 | 55 | Schema.createSchema(movieSchema) 56 | .then((schema) { 57 | var validator = new Validator(schema); 58 | bool validates = validator.validate(movies); 59 | if(!validates) { 60 | print("Errors: ${validator.errors}"); 61 | } else { 62 | print('$movies:\nvalidates!'); 63 | } 64 | }); 65 | 66 | } 67 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /test/test_invalid_schemas.dart: -------------------------------------------------------------------------------- 1 | library json_schema.test_invalid_schemas; 2 | 3 | import 'dart:convert' as convert; 4 | import 'dart:io'; 5 | import 'package:json_schema/json_schema.dart'; 6 | import 'package:logging/logging.dart'; 7 | import 'package:path/path.dart' as path; 8 | import 'package:test/test.dart'; 9 | 10 | // custom 11 | 12 | // end 13 | 14 | final Logger _logger = new Logger('test_invalid_schemas'); 15 | 16 | // custom 17 | // end 18 | 19 | void main([List args]) { 20 | if (args?.isEmpty ?? false) { 21 | Logger.root.onRecord.listen( 22 | (LogRecord r) => print("${r.loggerName} [${r.level}]:\t${r.message}")); 23 | Logger.root.level = Level.OFF; 24 | } 25 | // custom
26 | 27 | String here = 28 | path.dirname(path.dirname(path.absolute(Platform.script.toFilePath()))); 29 | 30 | Directory testSuiteFolder = new Directory("${here}/test/invalid_schemas"); 31 | 32 | testSuiteFolder.listSync().forEach((testEntry) { 33 | String shortName = path.basename(testEntry.path); 34 | group("Invalid schema: ${shortName}", () { 35 | if (testEntry is File) { 36 | List tests = 37 | convert.JSON.decode((testEntry as File).readAsStringSync()); 38 | tests.forEach((testObject) { 39 | var schemaData = testObject["schema"]; 40 | var description = testObject["description"]; 41 | test(description, () { 42 | var gotException = (e) { 43 | _logger.info("Caught expected $e"); 44 | if (!(e is FormatException)) { 45 | _logger.info('${shortName} wtf it is a ${e.runtimeType}'); 46 | } 47 | expect(e is FormatException, true); 48 | }; 49 | var ensureInvalid = expectAsync(gotException); 50 | 51 | try { 52 | Schema.createSchema(schemaData).then(ensureInvalid); 53 | } on FormatException catch (e) { 54 | ensureInvalid(e); 55 | } catch (e) { 56 | ensureInvalid(e); 57 | } 58 | }); 59 | }); 60 | } 61 | }); 62 | }); 63 | 64 | // end
65 | } 66 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft3/additionalProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": 4 | "additionalProperties being false does not allow other properties", 5 | "schema": { 6 | "properties": {"foo": {}, "bar": {}}, 7 | "additionalProperties": false 8 | }, 9 | "tests": [ 10 | { 11 | "description": "no additional properties is valid", 12 | "data": {"foo": 1}, 13 | "valid": true 14 | }, 15 | { 16 | "description": "an additional property is invalid", 17 | "data": {"foo" : 1, "bar" : 2, "quux" : "boom"}, 18 | "valid": false 19 | }, 20 | { 21 | "description": "ignores non-objects", 22 | "data": [1, 2, 3], 23 | "valid": true 24 | } 25 | ] 26 | }, 27 | { 28 | "description": 29 | "additionalProperties allows a schema which should validate", 30 | "schema": { 31 | "properties": {"foo": {}, "bar": {}}, 32 | "additionalProperties": {"type": "boolean"} 33 | }, 34 | "tests": [ 35 | { 36 | "description": "no additional properties is valid", 37 | "data": {"foo": 1}, 38 | "valid": true 39 | }, 40 | { 41 | "description": "an additional valid property is valid", 42 | "data": {"foo" : 1, "bar" : 2, "quux" : true}, 43 | "valid": true 44 | }, 45 | { 46 | "description": "an additional invalid property is invalid", 47 | "data": {"foo" : 1, "bar" : 2, "quux" : 12}, 48 | "valid": false 49 | } 50 | ] 51 | }, 52 | { 53 | "description": "additionalProperties are allowed by default", 54 | "schema": {"properties": {"foo": {}, "bar": {}}}, 55 | "tests": [ 56 | { 57 | "description": "additional properties are allowed", 58 | "data": {"foo": 1, "bar": 2, "quux": true}, 59 | "valid": true 60 | } 61 | ] 62 | } 63 | ] 64 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft4/additionalProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": 4 | "additionalProperties being false does not allow other properties", 5 | "schema": { 6 | "properties": {"foo": {}, "bar": {}}, 7 | "additionalProperties": false 8 | }, 9 | "tests": [ 10 | { 11 | "description": "no additional properties is valid", 12 | "data": {"foo": 1}, 13 | "valid": true 14 | }, 15 | { 16 | "description": "an additional property is invalid", 17 | "data": {"foo" : 1, "bar" : 2, "quux" : "boom"}, 18 | "valid": false 19 | }, 20 | { 21 | "description": "ignores non-objects", 22 | "data": [1, 2, 3], 23 | "valid": true 24 | } 25 | ] 26 | }, 27 | { 28 | "description": 29 | "additionalProperties allows a schema which should validate", 30 | "schema": { 31 | "properties": {"foo": {}, "bar": {}}, 32 | "additionalProperties": {"type": "boolean"} 33 | }, 34 | "tests": [ 35 | { 36 | "description": "no additional properties is valid", 37 | "data": {"foo": 1}, 38 | "valid": true 39 | }, 40 | { 41 | "description": "an additional valid property is valid", 42 | "data": {"foo" : 1, "bar" : 2, "quux" : true}, 43 | "valid": true 44 | }, 45 | { 46 | "description": "an additional invalid property is invalid", 47 | "data": {"foo" : 1, "bar" : 2, "quux" : 12}, 48 | "valid": false 49 | } 50 | ] 51 | }, 52 | { 53 | "description": "additionalProperties are allowed by default", 54 | "schema": {"properties": {"foo": {}, "bar": {}}}, 55 | "tests": [ 56 | { 57 | "description": "additional properties are allowed", 58 | "data": {"foo": 1, "bar": 2, "quux": true}, 59 | "valid": true 60 | } 61 | ] 62 | } 63 | ] 64 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft4/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 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /example/from_url/validate_instance_from_url.dart: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env dart 2 | 3 | import "dart:convert" as convert; 4 | import "package:json_schema/json_schema.dart"; 5 | import "package:logging/logging.dart"; 6 | 7 | main() { 8 | 9 | Logger.root.onRecord.listen((LogRecord rec) => 10 | print('${rec.level.name}: ${rec.time}: ${rec.message}')); 11 | Logger.root.level = Level.SHOUT; 12 | 13 | ////////////////////////////////////////////////////////////////////// 14 | // Pull in schema from web 15 | ////////////////////////////////////////////////////////////////////// 16 | String url = "http://json-schema.org/draft-04/schema"; 17 | Schema.createSchemaFromUrl(url) 18 | .then((Schema schema) { 19 | 20 | // TODO: Figure out the redirect issues here 21 | if(false) { 22 | print('''Does schema validate itself? 23 | ${schema.validate(schema.schemaMap)}'''); 24 | } 25 | 26 | var validSchema = { "type" : "integer" }; 27 | print('''Does schema validate valid schema $validSchema? 28 | ${schema.validate(validSchema)}'''); 29 | 30 | var invalidSchema = { "type" : "nibble" }; 31 | print('''Does schema validate invalid schema $invalidSchema? 32 | ${schema.validate(invalidSchema)}'''); 33 | 34 | }); 35 | 36 | ////////////////////////////////////////////////////////////////////// 37 | // Pull in schema from file in current directory 38 | ////////////////////////////////////////////////////////////////////// 39 | url = "grades_schema.json"; 40 | Schema.createSchemaFromUrl(url) 41 | .then((schema) { 42 | var grades = convert.JSON.decode(''' 43 | { 44 | "semesters": [ 45 | { 46 | "semester": 1, 47 | "grades": [ 48 | { 49 | "type": "homework", 50 | "date": "09/27/2013", 51 | "grade": 100, 52 | "avg": 93, 53 | "std": 8 54 | }, 55 | { 56 | "type": "homework", 57 | "date": "09/28/2013", 58 | "grade": 100, 59 | "avg": 60, 60 | "std": 25 61 | } 62 | ] 63 | } 64 | ] 65 | }'''); 66 | 67 | print('''Does grades schema validate $grades 68 | ${schema.validate(grades)}'''); 69 | }); 70 | } 71 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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": "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": [{"type": "integer"}]}, 74 | "tests": [ 75 | { 76 | "description": "only the first item is validated", 77 | "data": [1, "foo", false], 78 | "valid": true 79 | } 80 | ] 81 | } 82 | ] 83 | -------------------------------------------------------------------------------- /dot_samples/schemaout/movies.dot: -------------------------------------------------------------------------------- 1 | digraph G { 2 | fontname = "Bitstream Vera Sans" 3 | fontsize = 8 4 | 5 | node [ 6 | fontname = "Courier" 7 | fontsize = 8 8 | shape = "plaintext" 9 | ] 10 | 11 | edge [ 12 | fontname = "Bitstream Vera Sans" 13 | fontsize = 8 14 | ] 15 | 16 | "#" [ 17 | label =< 18 | 19 | 20 | 21 | 22 | 23 | movie 24 | movie_map 25 | 26 | ! movies 27 |
#
title=movie data
Definitions
movie
movie_map
Properties
! moviesobject
28 | > 29 | ] 30 | "#/definitions/movie" [ 31 | label =< 32 | 33 | 34 | 35 | 36 | 37 | ! rating 38 | ! title 39 | ! year_made 40 |
#/definitions/movie
Properties
! ratinginteger
! titlestring
! year_madeinteger
41 | > 42 | ] 43 | "#/definitions/movie_map" [ 44 | label =< 45 | 46 | 47 | 48 | 49 | 50 | Must Be: 51 | default 52 |
#/definitions/movie_map
Additional Properties
Must Be: {additionalProperties: fals...
default{}
53 | > 54 | ] 55 | "#":"@movies" -> "#/definitions/movie_map":"@path"; 56 | "#/definitions/movie_map":"mustBe" -> "#/definitions/movie":"@path"; 57 | 58 | 59 | } 60 | 61 | -------------------------------------------------------------------------------- /dot_samples/original/json-patch.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "JSON Patch", 3 | "description": "A JSON Schema describing a JSON Patch", 4 | "$schema": "http://json-schema.org/draft-04/schema#", 5 | "notes": [ 6 | "Only required members are accounted for, other members are ignored" 7 | ], 8 | "type": "array", 9 | "items": { 10 | "description": "one JSON Patch operation", 11 | "allOf": [ 12 | { 13 | "description": "Members common to all operations", 14 | "type": "object", 15 | "required": [ "op", "path" ], 16 | "properties": { 17 | "path": { "$ref": "#/definitions/jsonPointer" } 18 | } 19 | }, 20 | { "$ref": "#/definitions/oneOperation" } 21 | ] 22 | }, 23 | "definitions": { 24 | "jsonPointer": { 25 | "type": "string", 26 | "pattern": "^(/[^/~]*(~[01][^/~]*)*)*$" 27 | }, 28 | "add": { 29 | "description": "add operation. Value can be any JSON value.", 30 | "properties": { "op": { "enum": [ "add" ] } }, 31 | "required": [ "value" ] 32 | }, 33 | "remove": { 34 | "description": "remove operation. Only a path is specified.", 35 | "properties": { "op": { "enum": [ "remove" ] } } 36 | }, 37 | "replace": { 38 | "description": "replace operation. Value can be any JSON value.", 39 | "properties": { "op": { "enum": [ "replace" ] } }, 40 | "required": [ "value" ] 41 | }, 42 | "move": { 43 | "description": "move operation. \"from\" is a JSON Pointer.", 44 | "properties": { 45 | "op": { "enum": [ "move" ] }, 46 | "from": { "$ref": "#/definitions/jsonPointer" } 47 | }, 48 | "required": [ "from" ] 49 | }, 50 | "copy": { 51 | "description": "copy operation. \"from\" is a JSON Pointer.", 52 | "properties": { 53 | "op": { "enum": [ "copy" ] }, 54 | "from": { "$ref": "#/definitions/jsonPointer" } 55 | }, 56 | "required": [ "from" ] 57 | }, 58 | "test": { 59 | "description": "test operation. Value can be any JSON value.", 60 | "properties": { "op": { "enum": [ "test" ] } }, 61 | "required": [ "value" ] 62 | }, 63 | "oneOperation": { 64 | "oneOf": [ 65 | { "$ref": "#/definitions/add" }, 66 | { "$ref": "#/definitions/remove" }, 67 | { "$ref": "#/definitions/replace" }, 68 | { "$ref": "#/definitions/move" }, 69 | { "$ref": "#/definitions/copy" }, 70 | { "$ref": "#/definitions/test" } 71 | ] 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /dot_samples/schemas/json-patch.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "JSON Patch", 3 | "description": "A JSON Schema describing a JSON Patch", 4 | "$schema": "http://json-schema.org/draft-04/schema#", 5 | "notes": [ 6 | "Only required members are accounted for, other members are ignored" 7 | ], 8 | "type": "array", 9 | "items": { 10 | "description": "one JSON Patch operation", 11 | "allOf": [ 12 | { 13 | "description": "Members common to all operations", 14 | "type": "object", 15 | "required": [ "op", "path" ], 16 | "properties": { 17 | "path": { "$ref": "#/definitions/jsonPointer" } 18 | } 19 | }, 20 | { "$ref": "#/definitions/oneOperation" } 21 | ] 22 | }, 23 | "definitions": { 24 | "jsonPointer": { 25 | "type": "string", 26 | "pattern": "^(/[^/~]*(~[01][^/~]*)*)*$" 27 | }, 28 | "add": { 29 | "description": "add operation. Value can be any JSON value.", 30 | "properties": { "op": { "enum": [ "add" ] } }, 31 | "required": [ "value" ] 32 | }, 33 | "remove": { 34 | "description": "remove operation. Only a path is specified.", 35 | "properties": { "op": { "enum": [ "remove" ] } } 36 | }, 37 | "replace": { 38 | "description": "replace operation. Value can be any JSON value.", 39 | "properties": { "op": { "enum": [ "replace" ] } }, 40 | "required": [ "value" ] 41 | }, 42 | "move": { 43 | "description": "move operation. \"from\" is a JSON Pointer.", 44 | "properties": { 45 | "op": { "enum": [ "move" ] }, 46 | "from": { "$ref": "#/definitions/jsonPointer" } 47 | }, 48 | "required": [ "from" ] 49 | }, 50 | "copy": { 51 | "description": "copy operation. \"from\" is a JSON Pointer.", 52 | "properties": { 53 | "op": { "enum": [ "copy" ] }, 54 | "from": { "$ref": "#/definitions/jsonPointer" } 55 | }, 56 | "required": [ "from" ] 57 | }, 58 | "test": { 59 | "description": "test operation. Value can be any JSON value.", 60 | "properties": { "op": { "enum": [ "test" ] } }, 61 | "required": [ "value" ] 62 | }, 63 | "oneOperation": { 64 | "oneOf": [ 65 | { "$ref": "#/definitions/add" }, 66 | { "$ref": "#/definitions/remove" }, 67 | { "$ref": "#/definitions/replace" }, 68 | { "$ref": "#/definitions/move" }, 69 | { "$ref": "#/definitions/copy" }, 70 | { "$ref": "#/definitions/test" } 71 | ] 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft3/uniqueItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "uniqueItems validation", 4 | "schema": {"uniqueItems": true}, 5 | "tests": [ 6 | { 7 | "description": "unique array of integers is valid", 8 | "data": [1, 2], 9 | "valid": true 10 | }, 11 | { 12 | "description": "non-unique array of integers is invalid", 13 | "data": [1, 1], 14 | "valid": false 15 | }, 16 | { 17 | "description": "numbers are unique if mathematically unequal", 18 | "data": [1.0, 1.00, 1], 19 | "valid": false 20 | }, 21 | { 22 | "description": "unique array of objects is valid", 23 | "data": [{"foo": "bar"}, {"foo": "baz"}], 24 | "valid": true 25 | }, 26 | { 27 | "description": "non-unique array of objects is invalid", 28 | "data": [{"foo": "bar"}, {"foo": "bar"}], 29 | "valid": false 30 | }, 31 | { 32 | "description": "unique array of nested objects is valid", 33 | "data": [ 34 | {"foo": {"bar" : {"baz" : true}}}, 35 | {"foo": {"bar" : {"baz" : false}}} 36 | ], 37 | "valid": true 38 | }, 39 | { 40 | "description": "non-unique array of nested objects is invalid", 41 | "data": [ 42 | {"foo": {"bar" : {"baz" : true}}}, 43 | {"foo": {"bar" : {"baz" : true}}} 44 | ], 45 | "valid": false 46 | }, 47 | { 48 | "description": "unique array of arrays is valid", 49 | "data": [["foo"], ["bar"]], 50 | "valid": true 51 | }, 52 | { 53 | "description": "non-unique array of arrays is invalid", 54 | "data": [["foo"], ["foo"]], 55 | "valid": false 56 | }, 57 | { 58 | "description": "1 and true are unique", 59 | "data": [1, true], 60 | "valid": true 61 | }, 62 | { 63 | "description": "0 and false are unique", 64 | "data": [0, false], 65 | "valid": true 66 | }, 67 | { 68 | "description": "unique heterogeneous types are valid", 69 | "data": [{}, [1], true, null, 1], 70 | "valid": true 71 | }, 72 | { 73 | "description": "non-unique heterogeneous types are invalid", 74 | "data": [{}, [1], true, null, {}, 1], 75 | "valid": false 76 | } 77 | ] 78 | } 79 | ] 80 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft4/uniqueItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "uniqueItems validation", 4 | "schema": {"uniqueItems": true}, 5 | "tests": [ 6 | { 7 | "description": "unique array of integers is valid", 8 | "data": [1, 2], 9 | "valid": true 10 | }, 11 | { 12 | "description": "non-unique array of integers is invalid", 13 | "data": [1, 1], 14 | "valid": false 15 | }, 16 | { 17 | "description": "numbers are unique if mathematically unequal", 18 | "data": [1.0, 1.00, 1], 19 | "valid": false 20 | }, 21 | { 22 | "description": "unique array of objects is valid", 23 | "data": [{"foo": "bar"}, {"foo": "baz"}], 24 | "valid": true 25 | }, 26 | { 27 | "description": "non-unique array of objects is invalid", 28 | "data": [{"foo": "bar"}, {"foo": "bar"}], 29 | "valid": false 30 | }, 31 | { 32 | "description": "unique array of nested objects is valid", 33 | "data": [ 34 | {"foo": {"bar" : {"baz" : true}}}, 35 | {"foo": {"bar" : {"baz" : false}}} 36 | ], 37 | "valid": true 38 | }, 39 | { 40 | "description": "non-unique array of nested objects is invalid", 41 | "data": [ 42 | {"foo": {"bar" : {"baz" : true}}}, 43 | {"foo": {"bar" : {"baz" : true}}} 44 | ], 45 | "valid": false 46 | }, 47 | { 48 | "description": "unique array of arrays is valid", 49 | "data": [["foo"], ["bar"]], 50 | "valid": true 51 | }, 52 | { 53 | "description": "non-unique array of arrays is invalid", 54 | "data": [["foo"], ["foo"]], 55 | "valid": false 56 | }, 57 | { 58 | "description": "1 and true are unique", 59 | "data": [1, true], 60 | "valid": true 61 | }, 62 | { 63 | "description": "0 and false are unique", 64 | "data": [0, false], 65 | "valid": true 66 | }, 67 | { 68 | "description": "unique heterogeneous types are valid", 69 | "data": [{}, [1], true, null, 1], 70 | "valid": true 71 | }, 72 | { 73 | "description": "non-unique heterogeneous types are invalid", 74 | "data": [{}, [1], true, null, {}, 1], 75 | "valid": false 76 | } 77 | ] 78 | } 79 | ] 80 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/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 | -------------------------------------------------------------------------------- /dot_samples/original/geometry.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "id": "http://json-schema.org/geojson/geometry.json#", 4 | "title": "geometry", 5 | "description": "One geometry as defined by GeoJSON", 6 | "type": "object", 7 | "required": [ "type", "coordinates" ], 8 | "oneOf": [ 9 | { 10 | "title": "Point", 11 | "properties": { 12 | "type": { "enum": [ "Point" ] }, 13 | "coordinates": { "$ref": "#/definitions/position" } 14 | } 15 | }, 16 | { 17 | "title": "MultiPoint", 18 | "properties": { 19 | "type": { "enum": [ "MultiPoint" ] }, 20 | "coordinates": { "$ref": "#/definitions/positionArray" } 21 | } 22 | }, 23 | { 24 | "title": "LineString", 25 | "properties": { 26 | "type": { "enum": [ "LineString" ] }, 27 | "coordinates": { "$ref": "#/definitions/lineString" } 28 | } 29 | }, 30 | { 31 | "title": "MultiLineString", 32 | "properties": { 33 | "type": { "enum": [ "MultiLineString" ] }, 34 | "coordinates": { 35 | "type": "array", 36 | "items": { "$ref": "#/definitions/lineString" } 37 | } 38 | } 39 | }, 40 | { 41 | "title": "Polygon", 42 | "properties": { 43 | "type": { "enum": [ "Polygon" ] }, 44 | "coordinates": { "$ref": "#/definitions/polygon" } 45 | } 46 | }, 47 | { 48 | "title": "MultiPolygon", 49 | "properties": { 50 | "type": { "enum": [ "MultiPolygon" ] }, 51 | "coordinates": { 52 | "type": "array", 53 | "items": { "$ref": "#/definitions/polygon" } 54 | } 55 | } 56 | } 57 | ], 58 | "definitions": { 59 | "position": { 60 | "description": "A single position", 61 | "type": "array", 62 | "minItems": 2, 63 | "items": [ { "type": "number" }, { "type": "number" } ], 64 | "additionalItems": false 65 | }, 66 | "positionArray": { 67 | "description": "An array of positions", 68 | "type": "array", 69 | "items": { "$ref": "#/definitions/position" } 70 | }, 71 | "lineString": { 72 | "description": "An array of two or more positions", 73 | "allOf": [ 74 | { "$ref": "#/definitions/positionArray" }, 75 | { "minItems": 2 } 76 | ] 77 | }, 78 | "linearRing": { 79 | "description": "An array of four positions where the first equals the last", 80 | "allOf": [ 81 | { "$ref": "#/definitions/positionArray" }, 82 | { "minItems": 4 } 83 | ] 84 | }, 85 | "polygon": { 86 | "description": "An array of linear rings", 87 | "type": "array", 88 | "items": { "$ref": "#/definitions/linearRing" } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /dot_samples/schemas/geometry.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "id": "http://json-schema.org/geojson/geometry.json#", 4 | "title": "geometry", 5 | "description": "One geometry as defined by GeoJSON", 6 | "type": "object", 7 | "required": [ "type", "coordinates" ], 8 | "oneOf": [ 9 | { 10 | "title": "Point", 11 | "properties": { 12 | "type": { "enum": [ "Point" ] }, 13 | "coordinates": { "$ref": "#/definitions/position" } 14 | } 15 | }, 16 | { 17 | "title": "MultiPoint", 18 | "properties": { 19 | "type": { "enum": [ "MultiPoint" ] }, 20 | "coordinates": { "$ref": "#/definitions/positionArray" } 21 | } 22 | }, 23 | { 24 | "title": "LineString", 25 | "properties": { 26 | "type": { "enum": [ "LineString" ] }, 27 | "coordinates": { "$ref": "#/definitions/lineString" } 28 | } 29 | }, 30 | { 31 | "title": "MultiLineString", 32 | "properties": { 33 | "type": { "enum": [ "MultiLineString" ] }, 34 | "coordinates": { 35 | "type": "array", 36 | "items": { "$ref": "#/definitions/lineString" } 37 | } 38 | } 39 | }, 40 | { 41 | "title": "Polygon", 42 | "properties": { 43 | "type": { "enum": [ "Polygon" ] }, 44 | "coordinates": { "$ref": "#/definitions/polygon" } 45 | } 46 | }, 47 | { 48 | "title": "MultiPolygon", 49 | "properties": { 50 | "type": { "enum": [ "MultiPolygon" ] }, 51 | "coordinates": { 52 | "type": "array", 53 | "items": { "$ref": "#/definitions/polygon" } 54 | } 55 | } 56 | } 57 | ], 58 | "definitions": { 59 | "position": { 60 | "description": "A single position", 61 | "type": "array", 62 | "minItems": 2, 63 | "items": [ { "type": "number" }, { "type": "number" } ], 64 | "additionalItems": false 65 | }, 66 | "positionArray": { 67 | "description": "An array of positions", 68 | "type": "array", 69 | "items": { "$ref": "#/definitions/position" } 70 | }, 71 | "lineString": { 72 | "description": "An array of two or more positions", 73 | "allOf": [ 74 | { "$ref": "#/definitions/positionArray" }, 75 | { "minItems": 2 } 76 | ] 77 | }, 78 | "linearRing": { 79 | "description": "An array of four positions where the first equals the last", 80 | "allOf": [ 81 | { "$ref": "#/definitions/positionArray" }, 82 | { "minItems": 4 } 83 | ] 84 | }, 85 | "polygon": { 86 | "description": "An array of linear rings", 87 | "type": "array", 88 | "items": { "$ref": "#/definitions/linearRing" } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft3/properties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "object properties validation", 4 | "schema": { 5 | "properties": { 6 | "foo": {"type": "integer"}, 7 | "bar": {"type": "string"} 8 | } 9 | }, 10 | "tests": [ 11 | { 12 | "description": "both properties present and valid is valid", 13 | "data": {"foo": 1, "bar": "baz"}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "one property invalid is invalid", 18 | "data": {"foo": 1, "bar": {}}, 19 | "valid": false 20 | }, 21 | { 22 | "description": "both properties invalid is invalid", 23 | "data": {"foo": [], "bar": {}}, 24 | "valid": false 25 | }, 26 | { 27 | "description": "doesn't invalidate other properties", 28 | "data": {"quux": []}, 29 | "valid": true 30 | }, 31 | { 32 | "description": "ignores non-objects", 33 | "data": [], 34 | "valid": true 35 | } 36 | ] 37 | }, 38 | { 39 | "description": 40 | "properties, patternProperties, additionalProperties interaction", 41 | "schema": { 42 | "properties": { 43 | "foo": {"type": "array", "maxItems": 3}, 44 | "bar": {"type": "array"} 45 | }, 46 | "patternProperties": {"f.o": {"minItems": 2}}, 47 | "additionalProperties": {"type": "integer"} 48 | }, 49 | "tests": [ 50 | { 51 | "description": "property validates property", 52 | "data": {"foo": [1, 2]}, 53 | "valid": true 54 | }, 55 | { 56 | "description": "property invalidates property", 57 | "data": {"foo": [1, 2, 3, 4]}, 58 | "valid": false 59 | }, 60 | { 61 | "description": "patternProperty invalidates property", 62 | "data": {"foo": []}, 63 | "valid": false 64 | }, 65 | { 66 | "description": "patternProperty validates nonproperty", 67 | "data": {"fxo": [1, 2]}, 68 | "valid": true 69 | }, 70 | { 71 | "description": "patternProperty invalidates nonproperty", 72 | "data": {"fxo": []}, 73 | "valid": false 74 | }, 75 | { 76 | "description": "additionalProperty ignores property", 77 | "data": {"bar": []}, 78 | "valid": true 79 | }, 80 | { 81 | "description": "additionalProperty validates others", 82 | "data": {"quux": 3}, 83 | "valid": true 84 | }, 85 | { 86 | "description": "additionalProperty invalidates others", 87 | "data": {"quux": "foo"}, 88 | "valid": false 89 | } 90 | ] 91 | } 92 | ] 93 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft4/properties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "object properties validation", 4 | "schema": { 5 | "properties": { 6 | "foo": {"type": "integer"}, 7 | "bar": {"type": "string"} 8 | } 9 | }, 10 | "tests": [ 11 | { 12 | "description": "both properties present and valid is valid", 13 | "data": {"foo": 1, "bar": "baz"}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "one property invalid is invalid", 18 | "data": {"foo": 1, "bar": {}}, 19 | "valid": false 20 | }, 21 | { 22 | "description": "both properties invalid is invalid", 23 | "data": {"foo": [], "bar": {}}, 24 | "valid": false 25 | }, 26 | { 27 | "description": "doesn't invalidate other properties", 28 | "data": {"quux": []}, 29 | "valid": true 30 | }, 31 | { 32 | "description": "ignores non-objects", 33 | "data": [], 34 | "valid": true 35 | } 36 | ] 37 | }, 38 | { 39 | "description": 40 | "properties, patternProperties, additionalProperties interaction", 41 | "schema": { 42 | "properties": { 43 | "foo": {"type": "array", "maxItems": 3}, 44 | "bar": {"type": "array"} 45 | }, 46 | "patternProperties": {"f.o": {"minItems": 2}}, 47 | "additionalProperties": {"type": "integer"} 48 | }, 49 | "tests": [ 50 | { 51 | "description": "property validates property", 52 | "data": {"foo": [1, 2]}, 53 | "valid": true 54 | }, 55 | { 56 | "description": "property invalidates property", 57 | "data": {"foo": [1, 2, 3, 4]}, 58 | "valid": false 59 | }, 60 | { 61 | "description": "patternProperty invalidates property", 62 | "data": {"foo": []}, 63 | "valid": false 64 | }, 65 | { 66 | "description": "patternProperty validates nonproperty", 67 | "data": {"fxo": [1, 2]}, 68 | "valid": true 69 | }, 70 | { 71 | "description": "patternProperty invalidates nonproperty", 72 | "data": {"fxo": []}, 73 | "valid": false 74 | }, 75 | { 76 | "description": "additionalProperty ignores property", 77 | "data": {"bar": []}, 78 | "valid": true 79 | }, 80 | { 81 | "description": "additionalProperty validates others", 82 | "data": {"quux": 3}, 83 | "valid": true 84 | }, 85 | { 86 | "description": "additionalProperty invalidates others", 87 | "data": {"quux": "foo"}, 88 | "valid": false 89 | } 90 | ] 91 | } 92 | ] 93 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/README.md: -------------------------------------------------------------------------------- 1 | JSON Schema Test Suite [![Build Status](https://travis-ci.org/json-schema/JSON-Schema-Test-Suite.png?branch=develop)](https://travis-ci.org/json-schema/JSON-Schema-Test-Suite) 2 | ====================== 3 | 4 | This repository contains a set of JSON objects that implementors of JSON Schema 5 | validation libraries can use to test their validators. 6 | 7 | It is meant to be language agnostic and should require only a JSON parser. 8 | 9 | The conversion of the JSON objects into tests within your test framework of 10 | choice is still the job of the validator implementor. 11 | 12 | Structure of a Test 13 | ------------------- 14 | 15 | If you're going to use this suite, you need to know how tests are laid out. The 16 | tests are contained in the `tests` directory at the root of this repository. 17 | 18 | Inside that directory is a subdirectory for each draft or version of the 19 | schema. We'll use `draft3` as an example. 20 | 21 | If you look inside the draft directory, there are a number of `.json` files, 22 | which logically group a set of test cases together. Often the grouping is by 23 | property under test, but not always, especially within optional test files 24 | (discussed below). 25 | 26 | Inside each `.json` file is a single array containing objects. It's easiest to 27 | illustrate the structure of these with an example: 28 | 29 | ```json 30 | { 31 | "description": "the description of the test case", 32 | "schema": {"the schema that should" : "be validated against"}, 33 | "tests": [ 34 | { 35 | "description": "a specific test of a valid instance", 36 | "data": "the instance", 37 | "valid": true 38 | }, 39 | { 40 | "description": "another specific test this time, invalid", 41 | "data": 15, 42 | "valid": false 43 | } 44 | ] 45 | } 46 | ``` 47 | 48 | So a description, a schema, and some tests, where tests is an array containing 49 | one or more objects with descriptions, data, and a boolean indicating whether 50 | they should be valid or invalid. 51 | 52 | Coverage 53 | -------- 54 | 55 | Draft 3 and 4 should have full coverage. If you see anything missing or think 56 | there is a useful test missing, please send a pull request or open an issue. 57 | 58 | Who Uses the Test Suite 59 | ----------------------- 60 | 61 | This suite is being used by: 62 | 63 | * [json-schema-validator (Java)](https://github.com/fge/json-schema-validator) 64 | * [jsonschema (python)](https://github.com/Julian/jsonschema) 65 | * [aeson-schema (haskell)](https://github.com/timjb/aeson-schema) 66 | * [direct-schema (javascript)](https://github.com/IreneKnapp/direct-schema) 67 | * [jsonschema (javascript)](https://github.com/tdegrunt/jsonschema) 68 | * [JaySchema (javascript)](https://github.com/natesilva/jayschema) 69 | * [z-schema (javascript)](https://github.com/zaggino/z-schema) 70 | * [jesse (Erlang)](https://github.com/klarna/jesse) 71 | * [json-schema (PHP)](https://github.com/justinrainbow/json-schema) 72 | * [gojsonschema (Go)](https://github.com/sigu-399/gojsonschema) 73 | 74 | If you use it as well, please fork and send a pull request adding yourself to 75 | the list :). 76 | 77 | Contributing 78 | ------------ 79 | 80 | If you see something missing or incorrect, a pull request is most welcome! 81 | -------------------------------------------------------------------------------- /test/test_validation.dart: -------------------------------------------------------------------------------- 1 | library json_schema.test_validation; 2 | 3 | import 'dart:convert' as convert; 4 | import 'dart:io'; 5 | import 'package:json_schema/json_schema.dart'; 6 | import 'package:logging/logging.dart'; 7 | import 'package:path/path.dart' as path; 8 | import 'package:test/test.dart'; 9 | 10 | // custom 11 | // end 12 | 13 | final Logger _logger = new Logger('test_validation'); 14 | 15 | // custom 16 | // end 17 | 18 | void main([List args]) { 19 | if (args?.isEmpty ?? false) { 20 | Logger.root.onRecord.listen( 21 | (LogRecord r) => print("${r.loggerName} [${r.level}]:\t${r.message}")); 22 | Logger.root.level = Level.OFF; 23 | } 24 | // custom
25 | 26 | //////////////////////////////////////////////////////////////////////// 27 | // Uncomment to see logging of excpetions 28 | // Logger.root.onRecord.listen((LogRecord r) => 29 | // print("${r.loggerName} [${r.level}]:\t${r.message}")); 30 | 31 | Logger.root.level = Level.OFF; 32 | 33 | String here = 34 | path.dirname(path.dirname(path.absolute(Platform.script.toFilePath()))); 35 | 36 | Directory testSuiteFolder = new Directory( 37 | "${here}/test/JSON-Schema-Test-Suite/tests/draft4/invalidSchemas"); 38 | 39 | testSuiteFolder = 40 | new Directory("${here}/test/JSON-Schema-Test-Suite/tests/draft4"); 41 | 42 | var optionals = 43 | new Directory(path.joinAll([testSuiteFolder.path, 'optional'])); 44 | 45 | var all = testSuiteFolder.listSync()..addAll(optionals.listSync()); 46 | 47 | all.forEach((testEntry) { 48 | if (testEntry is File) { 49 | group("Validations ${path.basename(testEntry.path)}", () { 50 | // TODO: add these back or get replacements 51 | // Skip these for now - reason shown 52 | if ([ 53 | 'refRemote.json', // seems to require webserver running to vend files 54 | ].contains(path.basename(testEntry.path))) return; 55 | 56 | List tests = 57 | convert.JSON.decode((testEntry as File).readAsStringSync()); 58 | tests.forEach((testEntry) { 59 | var schemaData = testEntry["schema"]; 60 | var description = testEntry["description"]; 61 | List validationTests = testEntry["tests"]; 62 | 63 | validationTests.forEach((validationTest) { 64 | String validationDescription = validationTest["description"]; 65 | test("${description} : ${validationDescription}", () { 66 | var instance = validationTest["data"]; 67 | bool validationResult; 68 | bool expectedResult = validationTest["valid"]; 69 | var checkResult = 70 | expectAsync(() => expect(validationResult, expectedResult)); 71 | Schema.createSchema(schemaData).then((schema) { 72 | validationResult = schema.validate(instance); 73 | checkResult(); 74 | }); 75 | }); 76 | }); 77 | }); 78 | }); 79 | } 80 | }); 81 | 82 | test("Schema self validation", () { 83 | // Pull in the official schema, verify description and then ensure 84 | // that the schema satisfies the schema for schemas 85 | String url = "http://json-schema.org/draft-04/schema"; 86 | Schema.createSchemaFromUrl(url).then((schema) { 87 | expect(schema.schemaMap["description"], "Core schema meta-schema"); 88 | expect(schema.validate(schema.schemaMap), true); 89 | }); 90 | }); 91 | 92 | // end
93 | } 94 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft3/dependencies.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "dependencies", 4 | "schema": { 5 | "dependencies": {"bar": "foo"} 6 | }, 7 | "tests": [ 8 | { 9 | "description": "neither", 10 | "data": {}, 11 | "valid": true 12 | }, 13 | { 14 | "description": "nondependant", 15 | "data": {"foo": 1}, 16 | "valid": true 17 | }, 18 | { 19 | "description": "with dependency", 20 | "data": {"foo": 1, "bar": 2}, 21 | "valid": true 22 | }, 23 | { 24 | "description": "missing dependency", 25 | "data": {"bar": 2}, 26 | "valid": false 27 | }, 28 | { 29 | "description": "ignores non-objects", 30 | "data": "foo", 31 | "valid": true 32 | } 33 | ] 34 | }, 35 | { 36 | "description": "multiple dependencies", 37 | "schema": { 38 | "dependencies": {"quux": ["foo", "bar"]} 39 | }, 40 | "tests": [ 41 | { 42 | "description": "neither", 43 | "data": {}, 44 | "valid": true 45 | }, 46 | { 47 | "description": "nondependants", 48 | "data": {"foo": 1, "bar": 2}, 49 | "valid": true 50 | }, 51 | { 52 | "description": "with dependencies", 53 | "data": {"foo": 1, "bar": 2, "quux": 3}, 54 | "valid": true 55 | }, 56 | { 57 | "description": "missing dependency", 58 | "data": {"foo": 1, "quux": 2}, 59 | "valid": false 60 | }, 61 | { 62 | "description": "missing other dependency", 63 | "data": {"bar": 1, "quux": 2}, 64 | "valid": false 65 | }, 66 | { 67 | "description": "missing both dependencies", 68 | "data": {"quux": 1}, 69 | "valid": false 70 | } 71 | ] 72 | }, 73 | { 74 | "description": "multiple dependencies subschema", 75 | "schema": { 76 | "dependencies": { 77 | "bar": { 78 | "properties": { 79 | "foo": {"type": "integer"}, 80 | "bar": {"type": "integer"} 81 | } 82 | } 83 | } 84 | }, 85 | "tests": [ 86 | { 87 | "description": "valid", 88 | "data": {"foo": 1, "bar": 2}, 89 | "valid": true 90 | }, 91 | { 92 | "description": "wrong type", 93 | "data": {"foo": "quux", "bar": 2}, 94 | "valid": false 95 | }, 96 | { 97 | "description": "wrong type other", 98 | "data": {"foo": 2, "bar": "quux"}, 99 | "valid": false 100 | }, 101 | { 102 | "description": "wrong type both", 103 | "data": {"foo": "quux", "bar": "quux"}, 104 | "valid": false 105 | } 106 | ] 107 | } 108 | ] 109 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft4/allOf.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "allOf", 4 | "schema": { 5 | "allOf": [ 6 | { 7 | "properties": { 8 | "bar": {"type": "integer"} 9 | }, 10 | "required": ["bar"] 11 | }, 12 | { 13 | "properties": { 14 | "foo": {"type": "string"} 15 | }, 16 | "required": ["foo"] 17 | } 18 | ] 19 | }, 20 | "tests": [ 21 | { 22 | "description": "allOf", 23 | "data": {"foo": "baz", "bar": 2}, 24 | "valid": true 25 | }, 26 | { 27 | "description": "mismatch second", 28 | "data": {"foo": "baz"}, 29 | "valid": false 30 | }, 31 | { 32 | "description": "mismatch first", 33 | "data": {"bar": 2}, 34 | "valid": false 35 | }, 36 | { 37 | "description": "wrong type", 38 | "data": {"foo": "baz", "bar": "quux"}, 39 | "valid": false 40 | } 41 | ] 42 | }, 43 | { 44 | "description": "allOf with base schema", 45 | "schema": { 46 | "properties": {"bar": {"type": "integer"}}, 47 | "required": ["bar"], 48 | "allOf" : [ 49 | { 50 | "properties": { 51 | "foo": {"type": "string"} 52 | }, 53 | "required": ["foo"] 54 | }, 55 | { 56 | "properties": { 57 | "baz": {"type": "null"} 58 | }, 59 | "required": ["baz"] 60 | } 61 | ] 62 | }, 63 | "tests": [ 64 | { 65 | "description": "valid", 66 | "data": {"foo": "quux", "bar": 2, "baz": null}, 67 | "valid": true 68 | }, 69 | { 70 | "description": "mismatch base schema", 71 | "data": {"foo": "quux", "baz": null}, 72 | "valid": false 73 | }, 74 | { 75 | "description": "mismatch first allOf", 76 | "data": {"bar": 2, "baz": null}, 77 | "valid": false 78 | }, 79 | { 80 | "description": "mismatch second allOf", 81 | "data": {"foo": "quux", "bar": 2}, 82 | "valid": false 83 | }, 84 | { 85 | "description": "mismatch both", 86 | "data": {"bar": 2}, 87 | "valid": false 88 | } 89 | ] 90 | }, 91 | { 92 | "description": "allOf simple types", 93 | "schema": { 94 | "allOf": [ 95 | {"maximum": 30}, 96 | {"minimum": 20} 97 | ] 98 | }, 99 | "tests": [ 100 | { 101 | "description": "valid", 102 | "data": 25, 103 | "valid": true 104 | }, 105 | { 106 | "description": "mismatch one", 107 | "data": 35, 108 | "valid": false 109 | } 110 | ] 111 | } 112 | ] 113 | -------------------------------------------------------------------------------- /lib/json_schema.dart: -------------------------------------------------------------------------------- 1 | /// Support for validating json instances against a json schema 2 | library json_schema.json_schema; 3 | 4 | import 'dart:async'; 5 | import 'dart:convert' as convert; 6 | import 'dart:io'; 7 | import 'dart:math'; 8 | import 'package:logging/logging.dart'; 9 | import 'package:path/path.dart' as PATH; 10 | 11 | // custom 12 | // end 13 | 14 | part 'src/json_schema/schema.dart'; 15 | part 'src/json_schema/validator.dart'; 16 | 17 | final Logger _logger = new Logger('json_schema'); 18 | 19 | class SchemaType implements Comparable { 20 | static const SchemaType ARRAY = const SchemaType._(0); 21 | 22 | static const SchemaType BOOLEAN = const SchemaType._(1); 23 | 24 | static const SchemaType INTEGER = const SchemaType._(2); 25 | 26 | static const SchemaType NUMBER = const SchemaType._(3); 27 | 28 | static const SchemaType NULL = const SchemaType._(4); 29 | 30 | static const SchemaType OBJECT = const SchemaType._(5); 31 | 32 | static const SchemaType STRING = const SchemaType._(6); 33 | 34 | static List get values => 35 | const [ARRAY, BOOLEAN, INTEGER, NUMBER, NULL, OBJECT, STRING]; 36 | 37 | final int value; 38 | 39 | int get hashCode => value; 40 | 41 | const SchemaType._(this.value); 42 | 43 | SchemaType copy() => this; 44 | 45 | int compareTo(SchemaType other) => value.compareTo(other.value); 46 | 47 | String toString() { 48 | switch (this) { 49 | case ARRAY: 50 | return "array"; 51 | case BOOLEAN: 52 | return "boolean"; 53 | case INTEGER: 54 | return "integer"; 55 | case NUMBER: 56 | return "number"; 57 | case NULL: 58 | return "null"; 59 | case OBJECT: 60 | return "object"; 61 | case STRING: 62 | return "string"; 63 | } 64 | return null; 65 | } 66 | 67 | static SchemaType fromString(String s) { 68 | if (s == null) return null; 69 | switch (s) { 70 | case "array": 71 | return ARRAY; 72 | case "boolean": 73 | return BOOLEAN; 74 | case "integer": 75 | return INTEGER; 76 | case "number": 77 | return NUMBER; 78 | case "null": 79 | return NULL; 80 | case "object": 81 | return OBJECT; 82 | case "string": 83 | return STRING; 84 | default: 85 | return null; 86 | } 87 | } 88 | 89 | // custom 90 | // end 91 | 92 | } 93 | 94 | // custom 95 | 96 | /// Used to provide your own uri validator (if default does not suit needs) 97 | set uriValidator(bool validator(String s)) => _uriValidator = validator; 98 | 99 | /// Used to provide your own email validator (if default does not suit needs) 100 | set emailValidator(bool validator(String s)) => _emailValidator = validator; 101 | 102 | bool logFormatExceptions = false; 103 | 104 | bool _jsonEqual(a, b) { 105 | bool result = true; 106 | if (a is Map && b is Map) { 107 | if (a.length != b.length) return false; 108 | a.keys.forEach((k) { 109 | if (!_jsonEqual(a[k], b[k])) { 110 | result = false; 111 | return; 112 | } 113 | }); 114 | } else if (a is List && b is List) { 115 | if (a.length != b.length) return false; 116 | for (int i = 0; i < a.length; i++) { 117 | if (!_jsonEqual(a[i], b[i])) { 118 | return false; 119 | } 120 | } 121 | } else { 122 | return a == b; 123 | } 124 | return result; 125 | } 126 | 127 | // end 128 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft4/dependencies.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "dependencies", 4 | "schema": { 5 | "dependencies": {"bar": ["foo"]} 6 | }, 7 | "tests": [ 8 | { 9 | "description": "neither", 10 | "data": {}, 11 | "valid": true 12 | }, 13 | { 14 | "description": "nondependant", 15 | "data": {"foo": 1}, 16 | "valid": true 17 | }, 18 | { 19 | "description": "with dependency", 20 | "data": {"foo": 1, "bar": 2}, 21 | "valid": true 22 | }, 23 | { 24 | "description": "missing dependency", 25 | "data": {"bar": 2}, 26 | "valid": false 27 | }, 28 | { 29 | "description": "ignores non-objects", 30 | "data": "foo", 31 | "valid": true 32 | } 33 | ] 34 | }, 35 | { 36 | "description": "multiple dependencies", 37 | "schema": { 38 | "dependencies": {"quux": ["foo", "bar"]} 39 | }, 40 | "tests": [ 41 | { 42 | "description": "neither", 43 | "data": {}, 44 | "valid": true 45 | }, 46 | { 47 | "description": "nondependants", 48 | "data": {"foo": 1, "bar": 2}, 49 | "valid": true 50 | }, 51 | { 52 | "description": "with dependencies", 53 | "data": {"foo": 1, "bar": 2, "quux": 3}, 54 | "valid": true 55 | }, 56 | { 57 | "description": "missing dependency", 58 | "data": {"foo": 1, "quux": 2}, 59 | "valid": false 60 | }, 61 | { 62 | "description": "missing other dependency", 63 | "data": {"bar": 1, "quux": 2}, 64 | "valid": false 65 | }, 66 | { 67 | "description": "missing both dependencies", 68 | "data": {"quux": 1}, 69 | "valid": false 70 | } 71 | ] 72 | }, 73 | { 74 | "description": "multiple dependencies subschema", 75 | "schema": { 76 | "dependencies": { 77 | "bar": { 78 | "properties": { 79 | "foo": {"type": "integer"}, 80 | "bar": {"type": "integer"} 81 | } 82 | } 83 | } 84 | }, 85 | "tests": [ 86 | { 87 | "description": "valid", 88 | "data": {"foo": 1, "bar": 2}, 89 | "valid": true 90 | }, 91 | { 92 | "description": "no dependency", 93 | "data": {"foo": "quux"}, 94 | "valid": true 95 | }, 96 | { 97 | "description": "wrong type", 98 | "data": {"foo": "quux", "bar": 2}, 99 | "valid": false 100 | }, 101 | { 102 | "description": "wrong type other", 103 | "data": {"foo": 2, "bar": "quux"}, 104 | "valid": false 105 | }, 106 | { 107 | "description": "wrong type both", 108 | "data": {"foo": "quux", "bar": "quux"}, 109 | "valid": false 110 | } 111 | ] 112 | } 113 | ] 114 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft3/patternProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": 4 | "patternProperties validates properties matching a regex", 5 | "schema": { 6 | "patternProperties": { 7 | "f.*o": {"type": "integer"} 8 | } 9 | }, 10 | "tests": [ 11 | { 12 | "description": "a single valid match is valid", 13 | "data": {"foo": 1}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "multiple valid matches is valid", 18 | "data": {"foo": 1, "foooooo" : 2}, 19 | "valid": true 20 | }, 21 | { 22 | "description": "a single invalid match is invalid", 23 | "data": {"foo": "bar", "fooooo": 2}, 24 | "valid": false 25 | }, 26 | { 27 | "description": "multiple invalid matches is invalid", 28 | "data": {"foo": "bar", "foooooo" : "baz"}, 29 | "valid": false 30 | }, 31 | { 32 | "description": "ignores non-objects", 33 | "data": 12, 34 | "valid": true 35 | } 36 | ] 37 | }, 38 | { 39 | "description": "multiple simultaneous patternProperties are validated", 40 | "schema": { 41 | "patternProperties": { 42 | "a*": {"type": "integer"}, 43 | "aaa*": {"maximum": 20} 44 | } 45 | }, 46 | "tests": [ 47 | { 48 | "description": "a single valid match is valid", 49 | "data": {"a": 21}, 50 | "valid": true 51 | }, 52 | { 53 | "description": "a simultaneous match is valid", 54 | "data": {"aaaa": 18}, 55 | "valid": true 56 | }, 57 | { 58 | "description": "multiple matches is valid", 59 | "data": {"a": 21, "aaaa": 18}, 60 | "valid": true 61 | }, 62 | { 63 | "description": "an invalid due to one is invalid", 64 | "data": {"a": "bar"}, 65 | "valid": false 66 | }, 67 | { 68 | "description": "an invalid due to the other is invalid", 69 | "data": {"aaaa": 31}, 70 | "valid": false 71 | }, 72 | { 73 | "description": "an invalid due to both is invalid", 74 | "data": {"aaa": "foo", "aaaa": 31}, 75 | "valid": false 76 | } 77 | ] 78 | }, 79 | { 80 | "description": "regexes are not anchored by default and are case sensitive", 81 | "schema": { 82 | "patternProperties": { 83 | "[0-9]{2,}": { "type": "boolean" }, 84 | "X_": { "type": "string" } 85 | } 86 | }, 87 | "tests": [ 88 | { 89 | "description": "non recognized members are ignored", 90 | "data": { "answer 1": "42" }, 91 | "valid": true 92 | }, 93 | { 94 | "description": "recognized members are accounted for", 95 | "data": { "a31b": null }, 96 | "valid": false 97 | }, 98 | { 99 | "description": "regexes are case sensitive", 100 | "data": { "a_x_3": 3 }, 101 | "valid": true 102 | }, 103 | { 104 | "description": "regexes are case sensitive, 2", 105 | "data": { "a_X_3": 3 }, 106 | "valid": false 107 | } 108 | ] 109 | } 110 | ] 111 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft4/patternProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": 4 | "patternProperties validates properties matching a regex", 5 | "schema": { 6 | "patternProperties": { 7 | "f.*o": {"type": "integer"} 8 | } 9 | }, 10 | "tests": [ 11 | { 12 | "description": "a single valid match is valid", 13 | "data": {"foo": 1}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "multiple valid matches is valid", 18 | "data": {"foo": 1, "foooooo" : 2}, 19 | "valid": true 20 | }, 21 | { 22 | "description": "a single invalid match is invalid", 23 | "data": {"foo": "bar", "fooooo": 2}, 24 | "valid": false 25 | }, 26 | { 27 | "description": "multiple invalid matches is invalid", 28 | "data": {"foo": "bar", "foooooo" : "baz"}, 29 | "valid": false 30 | }, 31 | { 32 | "description": "ignores non-objects", 33 | "data": 12, 34 | "valid": true 35 | } 36 | ] 37 | }, 38 | { 39 | "description": "multiple simultaneous patternProperties are validated", 40 | "schema": { 41 | "patternProperties": { 42 | "a*": {"type": "integer"}, 43 | "aaa*": {"maximum": 20} 44 | } 45 | }, 46 | "tests": [ 47 | { 48 | "description": "a single valid match is valid", 49 | "data": {"a": 21}, 50 | "valid": true 51 | }, 52 | { 53 | "description": "a simultaneous match is valid", 54 | "data": {"aaaa": 18}, 55 | "valid": true 56 | }, 57 | { 58 | "description": "multiple matches is valid", 59 | "data": {"a": 21, "aaaa": 18}, 60 | "valid": true 61 | }, 62 | { 63 | "description": "an invalid due to one is invalid", 64 | "data": {"a": "bar"}, 65 | "valid": false 66 | }, 67 | { 68 | "description": "an invalid due to the other is invalid", 69 | "data": {"aaaa": 31}, 70 | "valid": false 71 | }, 72 | { 73 | "description": "an invalid due to both is invalid", 74 | "data": {"aaa": "foo", "aaaa": 31}, 75 | "valid": false 76 | } 77 | ] 78 | }, 79 | { 80 | "description": "regexes are not anchored by default and are case sensitive", 81 | "schema": { 82 | "patternProperties": { 83 | "[0-9]{2,}": { "type": "boolean" }, 84 | "X_": { "type": "string" } 85 | } 86 | }, 87 | "tests": [ 88 | { 89 | "description": "non recognized members are ignored", 90 | "data": { "answer 1": "42" }, 91 | "valid": true 92 | }, 93 | { 94 | "description": "recognized members are accounted for", 95 | "data": { "a31b": null }, 96 | "valid": false 97 | }, 98 | { 99 | "description": "regexes are case sensitive", 100 | "data": { "a_x_3": 3 }, 101 | "valid": true 102 | }, 103 | { 104 | "description": "regexes are case sensitive, 2", 105 | "data": { "a_X_3": 3 }, 106 | "valid": false 107 | } 108 | ] 109 | } 110 | ] 111 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft4/ref.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "root pointer ref", 4 | "schema": { 5 | "properties": { 6 | "foo": {"$ref": "#"} 7 | }, 8 | "additionalProperties": false 9 | }, 10 | "tests": [ 11 | { 12 | "description": "match", 13 | "data": {"foo": false}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "recursive match", 18 | "data": {"foo": {"foo": false}}, 19 | "valid": true 20 | }, 21 | { 22 | "description": "mismatch", 23 | "data": {"bar": false}, 24 | "valid": false 25 | }, 26 | { 27 | "description": "recursive mismatch", 28 | "data": {"foo": {"bar": false}}, 29 | "valid": false 30 | } 31 | ] 32 | }, 33 | { 34 | "description": "relative pointer ref to object", 35 | "schema": { 36 | "properties": { 37 | "foo": {"type": "integer"}, 38 | "bar": {"$ref": "#/properties/foo"} 39 | } 40 | }, 41 | "tests": [ 42 | { 43 | "description": "match", 44 | "data": {"bar": 3}, 45 | "valid": true 46 | }, 47 | { 48 | "description": "mismatch", 49 | "data": {"bar": true}, 50 | "valid": false 51 | } 52 | ] 53 | }, 54 | { 55 | "description": "relative pointer ref to array", 56 | "schema": { 57 | "items": [ 58 | {"type": "integer"}, 59 | {"$ref": "#/items/0"} 60 | ] 61 | }, 62 | "tests": [ 63 | { 64 | "description": "match array", 65 | "data": [1, 2], 66 | "valid": true 67 | }, 68 | { 69 | "description": "mismatch array", 70 | "data": [1, "foo"], 71 | "valid": false 72 | } 73 | ] 74 | }, 75 | { 76 | "description": "escaped pointer ref", 77 | "schema": { 78 | "tilda~field": {"type": "integer"}, 79 | "slash/field": {"type": "integer"}, 80 | "percent%field": {"type": "integer"}, 81 | "properties": { 82 | "tilda": {"$ref": "#/tilda~0field"}, 83 | "slash": {"$ref": "#/slash~1field"}, 84 | "percent": {"$ref": "#/percent%25field"} 85 | } 86 | }, 87 | "tests": [ 88 | { 89 | "description": "slash", 90 | "data": {"slash": "aoeu"}, 91 | "valid": false 92 | }, 93 | { 94 | "description": "tilda", 95 | "data": {"tilda": "aoeu"}, 96 | "valid": false 97 | }, 98 | { 99 | "description": "percent", 100 | "data": {"percent": "aoeu"}, 101 | "valid": false 102 | } 103 | ] 104 | }, 105 | { 106 | "description": "nested refs", 107 | "schema": { 108 | "definitions": { 109 | "a": {"type": "integer"}, 110 | "b": {"$ref": "#/definitions/a"}, 111 | "c": {"$ref": "#/definitions/b"} 112 | }, 113 | "$ref": "#/definitions/c" 114 | }, 115 | "tests": [ 116 | { 117 | "description": "nested ref valid", 118 | "data": 5, 119 | "valid": true 120 | }, 121 | { 122 | "description": "nested ref invalid", 123 | "data": "a", 124 | "valid": false 125 | } 126 | ] 127 | }, 128 | { 129 | "description": "remote ref, containing refs itself", 130 | "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, 131 | "tests": [ 132 | { 133 | "description": "remote ref valid", 134 | "data": {"minLength": 1}, 135 | "valid": true 136 | }, 137 | { 138 | "description": "remote ref invalid", 139 | "data": {"minLength": -1}, 140 | "valid": false 141 | } 142 | ] 143 | } 144 | ] 145 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft3/ref.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "root pointer ref", 4 | "schema": { 5 | "properties": { 6 | "foo": {"$ref": "#"} 7 | }, 8 | "additionalProperties": false 9 | }, 10 | "tests": [ 11 | { 12 | "description": "match", 13 | "data": {"foo": false}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "recursive match", 18 | "data": {"foo": {"foo": false}}, 19 | "valid": true 20 | }, 21 | { 22 | "description": "mismatch", 23 | "data": {"bar": false}, 24 | "valid": false 25 | }, 26 | { 27 | "description": "recursive mismatch", 28 | "data": {"foo": {"bar": false}}, 29 | "valid": false 30 | } 31 | ] 32 | }, 33 | { 34 | "description": "relative pointer ref to object", 35 | "schema": { 36 | "properties": { 37 | "foo": {"type": "integer"}, 38 | "bar": {"$ref": "#/properties/foo"} 39 | } 40 | }, 41 | "tests": [ 42 | { 43 | "description": "match", 44 | "data": {"bar": 3}, 45 | "valid": true 46 | }, 47 | { 48 | "description": "mismatch", 49 | "data": {"bar": true}, 50 | "valid": false 51 | } 52 | ] 53 | }, 54 | { 55 | "description": "relative pointer ref to array", 56 | "schema": { 57 | "items": [ 58 | {"type": "integer"}, 59 | {"$ref": "#/items/0"} 60 | ] 61 | }, 62 | "tests": [ 63 | { 64 | "description": "match array", 65 | "data": [1, 2], 66 | "valid": true 67 | }, 68 | { 69 | "description": "mismatch array", 70 | "data": [1, "foo"], 71 | "valid": false 72 | } 73 | ] 74 | }, 75 | { 76 | "description": "escaped pointer ref", 77 | "schema": { 78 | "tilda~field": {"type": "integer"}, 79 | "slash/field": {"type": "integer"}, 80 | "percent%field": {"type": "integer"}, 81 | "properties": { 82 | "tilda": {"$ref": "#/tilda~0field"}, 83 | "slash": {"$ref": "#/slash~1field"}, 84 | "percent": {"$ref": "#/percent%25field"} 85 | } 86 | }, 87 | "tests": [ 88 | { 89 | "description": "slash", 90 | "data": {"slash": "aoeu"}, 91 | "valid": false 92 | }, 93 | { 94 | "description": "tilda", 95 | "data": {"tilda": "aoeu"}, 96 | "valid": false 97 | }, 98 | { 99 | "description": "percent", 100 | "data": {"percent": "aoeu"}, 101 | "valid": false 102 | } 103 | ] 104 | }, 105 | { 106 | "description": "nested refs", 107 | "schema": { 108 | "definitions": { 109 | "a": {"type": "integer"}, 110 | "b": {"$ref": "#/definitions/a"}, 111 | "c": {"$ref": "#/definitions/b"} 112 | }, 113 | "$ref": "#/definitions/c" 114 | }, 115 | "tests": [ 116 | { 117 | "description": "nested ref valid", 118 | "data": 5, 119 | "valid": true 120 | }, 121 | { 122 | "description": "nested ref invalid", 123 | "data": "a", 124 | "valid": false 125 | } 126 | ] 127 | }, 128 | { 129 | "description": "remote ref, containing refs itself", 130 | "schema": {"$ref": "http://json-schema.org/draft-03/schema#"}, 131 | "tests": [ 132 | { 133 | "description": "remote ref valid", 134 | "data": {"items": {"type": "integer"}}, 135 | "valid": true 136 | }, 137 | { 138 | "description": "remote ref invalid", 139 | "data": {"items": {"type": 1}}, 140 | "valid": false 141 | } 142 | ] 143 | } 144 | ] 145 | -------------------------------------------------------------------------------- /dot_samples/schemaout/card.dot: -------------------------------------------------------------------------------- 1 | digraph G { 2 | fontname = "Bitstream Vera Sans" 3 | fontsize = 8 4 | 5 | node [ 6 | fontname = "Courier" 7 | fontsize = 8 8 | shape = "plaintext" 9 | ] 10 | 11 | edge [ 12 | fontname = "Bitstream Vera Sans" 13 | fontsize = 8 14 | ] 15 | 16 | "#" [ 17 | label =< 18 | 19 | 20 | 21 | 22 | 23 | ? additionalName 24 | ? bday 25 | ? email 26 | ! familyName 27 | ? fn 28 | ! givenName 29 | ? honorificPrefix 30 | ? honorificSuffix 31 | ? logo 32 | ? nickname 33 | ? org 34 | ? photo 35 | ? role 36 | ? sound 37 | ? tel 38 | ? title 39 | ? tz 40 | ? url 41 |
#
descr=A representation of a...
Properties
? additionalNamearray
? bdaystring
? emailobject
! familyNamestring
? fnstring
! givenNamestring
? honorificPrefixarray
? honorificSuffixarray
? logostring
? nicknamestring
? orgobject
? photostring
? rolestring
? soundstring
? telobject
? titlestring
? tzstring
? urlstring
42 | > 43 | ] 44 | "#/properties/email" [ 45 | label =< 46 | 47 | 48 | 49 | 50 | 51 | ? type 52 | ? value 53 |
#/properties/email
Properties
? typestring
? valuestring
54 | > 55 | ] 56 | "#/properties/tel" [ 57 | label =< 58 | 59 | 60 | 61 | 62 | 63 | ? type 64 | ? value 65 |
#/properties/tel
Properties
? typestring
? valuestring
66 | > 67 | ] 68 | "#/properties/org" [ 69 | label =< 70 | 71 | 72 | 73 | 74 | 75 | ? organizationName 76 | ? organizationUnit 77 |
#/properties/org
Properties
? organizationNamestring
? organizationUnitstring
78 | > 79 | ] 80 | "#":"@email" -> "#/properties/email":"@path"; 81 | "#":"@org" -> "#/properties/org":"@path"; 82 | "#":"@tel" -> "#/properties/tel":"@path"; 83 | 84 | 85 | } 86 | 87 | -------------------------------------------------------------------------------- /test/JSON-Schema-Test-Suite/tests/draft4/optional/format.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": "an invalid date-time string", 13 | "data": "06/19/1963 08:30:06 PST", 14 | "valid": false 15 | }, 16 | { 17 | "description": "only RFC3339 not all of ISO 8601 are valid", 18 | "data": "2013-350T01:01:01", 19 | "valid": false 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "validation of URIs", 25 | "schema": {"format": "uri"}, 26 | "tests": [ 27 | { 28 | "description": "a valid URI", 29 | "data": "http://foo.bar/?baz=qux#quux", 30 | "valid": true 31 | }, 32 | { 33 | "description": "an now valid URI", 34 | "data": "\\\\WINDOWS\\fileshare", 35 | "valid": true 36 | }, 37 | { 38 | "description": "a valid URI path part may not be //", 39 | "data": "http://ibm.com//goo", 40 | "valid": false 41 | } 42 | ] 43 | }, 44 | { 45 | "description": "validation of e-mail addresses", 46 | "schema": {"format": "email"}, 47 | "tests": [ 48 | { 49 | "description": "a valid e-mail address", 50 | "data": "joe.bloggs@example.com", 51 | "valid": true 52 | }, 53 | { 54 | "description": "an invalid e-mail address", 55 | "data": "2962", 56 | "valid": false 57 | } 58 | ] 59 | }, 60 | { 61 | "description": "validation of IP addresses", 62 | "schema": {"format": "ipv4"}, 63 | "tests": [ 64 | { 65 | "description": "a valid IP address", 66 | "data": "192.168.0.1", 67 | "valid": true 68 | }, 69 | { 70 | "description": "an IP address with too many components", 71 | "data": "127.0.0.0.1", 72 | "valid": false 73 | }, 74 | { 75 | "description": "an IP address with out-of-range values", 76 | "data": "256.256.256.256", 77 | "valid": false 78 | } 79 | ] 80 | }, 81 | { 82 | "description": "validation of IPv6 addresses", 83 | "schema": {"format": "ipv6"}, 84 | "tests": [ 85 | { 86 | "description": "a valid IPv6 address", 87 | "data": "::1", 88 | "valid": true 89 | }, 90 | { 91 | "description": "an IPv6 address with out-of-range values", 92 | "data": "12345::", 93 | "valid": false 94 | }, 95 | { 96 | "description": "an IPv6 address with too many components", 97 | "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1", 98 | "valid": false 99 | }, 100 | { 101 | "description": "an IPv6 address containing illegal characters", 102 | "data": "::laptop", 103 | "valid": false 104 | } 105 | ] 106 | }, 107 | { 108 | "description": "validation of host names", 109 | "schema": {"format": "hostname"}, 110 | "tests": [ 111 | { 112 | "description": "a valid host name", 113 | "data": "www.example.com", 114 | "valid": true 115 | }, 116 | { 117 | "description": "a host name starting with an illegal character", 118 | "data": "-a-host-name-that-starts-with--", 119 | "valid": false 120 | }, 121 | { 122 | "description": "a host name containing illegal characters", 123 | "data": "not_a_valid_host_name", 124 | "valid": false 125 | }, 126 | { 127 | "description": "a host name with a component too long", 128 | "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component", 129 | "valid": false 130 | } 131 | ] 132 | } 133 | ] 134 | -------------------------------------------------------------------------------- /dot_samples/schemas/draft04_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "http://json-schema.org/draft-04/schema#", 3 | "$schema": "http://json-schema.org/draft-04/schema#", 4 | "description": "Core schema meta-schema", 5 | "definitions": { 6 | "schemaArray": { 7 | "type": "array", 8 | "minItems": 1, 9 | "items": { "$ref": "#" } 10 | }, 11 | "positiveInteger": { 12 | "type": "integer", 13 | "minimum": 0 14 | }, 15 | "positiveIntegerDefault0": { 16 | "allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ] 17 | }, 18 | "simpleTypes": { 19 | "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ] 20 | }, 21 | "stringArray": { 22 | "type": "array", 23 | "items": { "type": "string" }, 24 | "minItems": 1, 25 | "uniqueItems": true 26 | } 27 | }, 28 | "type": "object", 29 | "properties": { 30 | "id": { 31 | "type": "string", 32 | "format": "uri" 33 | }, 34 | "$schema": { 35 | "type": "string", 36 | "format": "uri" 37 | }, 38 | "title": { 39 | "type": "string" 40 | }, 41 | "description": { 42 | "type": "string" 43 | }, 44 | "default": {}, 45 | "multipleOf": { 46 | "type": "number", 47 | "minimum": 0, 48 | "exclusiveMinimum": true 49 | }, 50 | "maximum": { 51 | "type": "number" 52 | }, 53 | "exclusiveMaximum": { 54 | "type": "boolean", 55 | "default": false 56 | }, 57 | "minimum": { 58 | "type": "number" 59 | }, 60 | "exclusiveMinimum": { 61 | "type": "boolean", 62 | "default": false 63 | }, 64 | "maxLength": { "$ref": "#/definitions/positiveInteger" }, 65 | "minLength": { "$ref": "#/definitions/positiveIntegerDefault0" }, 66 | "pattern": { 67 | "type": "string", 68 | "format": "regex" 69 | }, 70 | "additionalItems": { 71 | "anyOf": [ 72 | { "type": "boolean" }, 73 | { "$ref": "#" } 74 | ], 75 | "default": {} 76 | }, 77 | "items": { 78 | "anyOf": [ 79 | { "$ref": "#" }, 80 | { "$ref": "#/definitions/schemaArray" } 81 | ], 82 | "default": {} 83 | }, 84 | "maxItems": { "$ref": "#/definitions/positiveInteger" }, 85 | "minItems": { "$ref": "#/definitions/positiveIntegerDefault0" }, 86 | "uniqueItems": { 87 | "type": "boolean", 88 | "default": false 89 | }, 90 | "maxProperties": { "$ref": "#/definitions/positiveInteger" }, 91 | "minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" }, 92 | "required": { "$ref": "#/definitions/stringArray" }, 93 | "additionalProperties": { 94 | "anyOf": [ 95 | { "type": "boolean" }, 96 | { "$ref": "#" } 97 | ], 98 | "default": {} 99 | }, 100 | "definitions": { 101 | "type": "object", 102 | "additionalProperties": { "$ref": "#" }, 103 | "default": {} 104 | }, 105 | "properties": { 106 | "type": "object", 107 | "additionalProperties": { "$ref": "#" }, 108 | "default": {} 109 | }, 110 | "patternProperties": { 111 | "type": "object", 112 | "additionalProperties": { "$ref": "#" }, 113 | "default": {} 114 | }, 115 | "dependencies": { 116 | "type": "object", 117 | "additionalProperties": { 118 | "anyOf": [ 119 | { "$ref": "#" }, 120 | { "$ref": "#/definitions/stringArray" } 121 | ] 122 | } 123 | }, 124 | "enum": { 125 | "type": "array", 126 | "minItems": 1, 127 | "uniqueItems": true 128 | }, 129 | "type": { 130 | "anyOf": [ 131 | { "$ref": "#/definitions/simpleTypes" }, 132 | { 133 | "type": "array", 134 | "items": { "$ref": "#/definitions/simpleTypes" }, 135 | "minItems": 1, 136 | "uniqueItems": true 137 | } 138 | ] 139 | }, 140 | "allOf": { "$ref": "#/definitions/schemaArray" }, 141 | "anyOf": { "$ref": "#/definitions/schemaArray" }, 142 | "oneOf": { "$ref": "#/definitions/schemaArray" }, 143 | "not": { "$ref": "#" } 144 | }, 145 | "dependencies": { 146 | "exclusiveMaximum": [ "maximum" ], 147 | "exclusiveMinimum": [ "minimum" ] 148 | }, 149 | "default": {} 150 | } 151 | -------------------------------------------------------------------------------- /bin/schemadot.dart: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env dart 2 | 3 | /// 4 | /// Usage: schemadot --in-uri INPUT_JSON_URI --out-file OUTPUT_FILE 5 | /// 6 | /// Given an input uri [in-uri] processes content of uri as 7 | /// json schema and generates input file for Graphviz dot 8 | /// program. If [out-file] provided, output is written to 9 | /// the file, otherwise written to stdout. 10 | /// 11 | import 'dart:async'; 12 | import 'dart:convert' as convert; 13 | import 'dart:io'; 14 | import 'dart:math'; 15 | import 'package:args/args.dart'; 16 | import 'package:json_schema/json_schema.dart'; 17 | import 'package:json_schema/schema_dot.dart'; 18 | import 'package:logging/logging.dart'; 19 | 20 | // custom 21 | // end 22 | //! The parser for this script 23 | ArgParser _parser; 24 | //! The comment and usage associated with this script 25 | void _usage() { 26 | print(r''' 27 | 28 | Usage: schemadot --in-uri INPUT_JSON_URI --out-file OUTPUT_FILE 29 | 30 | Given an input uri [in-uri] processes content of uri as 31 | json schema and generates input file for Graphviz dot 32 | program. If [out-file] provided, output is written to 33 | the file, otherwise written to stdout. 34 | 35 | '''); 36 | print(_parser.getUsage()); 37 | } 38 | 39 | //! Method to parse command line options. 40 | //! The result is a map containing all options, including positional options 41 | Map _parseArgs(List args) { 42 | ArgResults argResults; 43 | Map result = {}; 44 | List remaining = []; 45 | 46 | _parser = new ArgParser(); 47 | try { 48 | /// Fill in expectations of the parser 49 | _parser.addFlag('help', 50 | help: r''' 51 | Display this help screen 52 | ''', 53 | abbr: 'h', 54 | defaultsTo: false); 55 | 56 | _parser.addOption('in-uri', 57 | help: '', 58 | defaultsTo: null, 59 | allowMultiple: false, 60 | abbr: 'i', 61 | allowed: null); 62 | _parser.addOption('out-file', 63 | help: '', 64 | defaultsTo: null, 65 | allowMultiple: false, 66 | abbr: 'o', 67 | allowed: null); 68 | _parser.addOption('log-level', 69 | help: r''' 70 | Select log level from: 71 | [ all, config, fine, finer, finest, info, levels, 72 | off, severe, shout, warning ] 73 | 74 | ''', 75 | defaultsTo: null, 76 | allowMultiple: false, 77 | abbr: null, 78 | allowed: null); 79 | 80 | /// Parse the command line options (excluding the script) 81 | argResults = _parser.parse(args); 82 | if (argResults.wasParsed('help')) { 83 | _usage(); 84 | exit(0); 85 | } 86 | result['in-uri'] = argResults['in-uri']; 87 | result['out-file'] = argResults['out-file']; 88 | result['help'] = argResults['help']; 89 | result['log-level'] = argResults['log-level']; 90 | 91 | if (result['log-level'] != null) { 92 | const choices = const { 93 | 'all': Level.ALL, 94 | 'config': Level.CONFIG, 95 | 'fine': Level.FINE, 96 | 'finer': Level.FINER, 97 | 'finest': Level.FINEST, 98 | 'info': Level.INFO, 99 | 'levels': Level.LEVELS, 100 | 'off': Level.OFF, 101 | 'severe': Level.SEVERE, 102 | 'shout': Level.SHOUT, 103 | 'warning': Level.WARNING 104 | }; 105 | final selection = choices[result['log-level'].toLowerCase()]; 106 | if (selection != null) Logger.root.level = selection; 107 | } 108 | 109 | return {'options': result, 'rest': argResults.rest}; 110 | } catch (e) { 111 | _usage(); 112 | throw e; 113 | } 114 | } 115 | 116 | final _logger = new Logger('schemadot'); 117 | 118 | main(List args) { 119 | Logger.root.onRecord.listen( 120 | (LogRecord r) => print("${r.loggerName} [${r.level}]:\t${r.message}")); 121 | Logger.root.level = Level.OFF; 122 | Map argResults = _parseArgs(args); 123 | Map options = argResults['options']; 124 | List positionals = argResults['rest']; 125 | try { 126 | if (options["in-uri"] == null) 127 | throw new ArgumentError("option: in-uri is required"); 128 | } on ArgumentError catch (e) { 129 | print(e); 130 | _usage(); 131 | exit(-1); 132 | } 133 | // custom 134 | 135 | Logger.root.level = Level.OFF; 136 | Completer completer = new Completer(); 137 | Uri uri = Uri.parse(options['in-uri']); 138 | if (uri.scheme == 'http') { 139 | new HttpClient() 140 | .getUrl(uri) 141 | .then((HttpClientRequest request) => request.close()) 142 | .then((HttpClientResponse response) => 143 | response.transform(new convert.Utf8Decoder()).join()) 144 | .then((text) { 145 | completer.complete(text); 146 | }); 147 | } else { 148 | File target = new File(uri.toString()); 149 | if (target.existsSync()) { 150 | completer.complete(target.readAsStringSync()); 151 | } 152 | } 153 | 154 | completer.future.then((schemaText) { 155 | Future schema = Schema.createSchema(convert.JSON.decode(schemaText)); 156 | schema.then((schema) { 157 | String dot = createDot(schema); 158 | if (options['out-file'] != null) { 159 | new File(options['out-file']).writeAsStringSync(dot); 160 | } else { 161 | print(dot); 162 | } 163 | }); 164 | }); 165 | 166 | // end 167 | } 168 | 169 | // custom 170 | 171 | // end 172 | -------------------------------------------------------------------------------- /dot_samples/original/avro-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title": "avro-schema", 4 | "description": "JSON Schema for an Apache Avro schema, version 1.7.3", 5 | "oneOf": [ 6 | { "type": "string" }, 7 | { 8 | "type": "object", 9 | "required": [ "type" ], 10 | "properties": { 11 | "type": { "$ref": "#/definitions/primitiveTypes" } 12 | } 13 | }, 14 | { "$ref": "#/definitions/record" }, 15 | { "$ref": "#/definitions/enum" }, 16 | { "$ref": "#/definitions/array" }, 17 | { "$ref": "#/definitions/map" }, 18 | { "$ref": "#/definitions/union" }, 19 | { "$ref": "#/definitions/fixed" } 20 | ], 21 | "definitions": { 22 | "primitiveTypes": { 23 | "description": "One primitive type", 24 | "enum": [ "null", "boolean", "int", "long", "float", "double", "bytes", "string" ] 25 | }, 26 | "record": { 27 | "description": "A record", 28 | "type": "object", 29 | "required": [ "type", "name", "fields" ], 30 | "properties": { 31 | "type": { "enum": [ "record" ] }, 32 | "name": { "$ref": "#/definitions/nameOrNamespace" }, 33 | "nameOrNamespace": { "$ref": "#/definitions/namespace" }, 34 | "doc": { "type": "string" }, 35 | "aliases": { "$ref": "#/definitions/aliases" }, 36 | "fields": { 37 | "type": "array", 38 | "items": { "$ref": "#/definitions/field" } 39 | } 40 | } 41 | }, 42 | "enum": { 43 | "description": "an enum as defined by the Avro specification", 44 | "type": "object", 45 | "required": [ "type", "name", "symbols" ], 46 | "properties": { 47 | "type": { "enum": [ "enum" ] }, 48 | "name": { "$ref": "#/definitions/nameOrNamespace" }, 49 | "nameOrNamespace": { "$ref": "#/definitions/namespace" }, 50 | "aliases": { "$ref": "#/definitions/aliases" }, 51 | "doc": { "type": "string" }, 52 | "symbols": { 53 | "type": "array", 54 | "minItems": 1, 55 | "items": { 56 | "type": "string", 57 | "minLength": 1, 58 | "pattern": "^(?![_\\d])\\w+$" 59 | }, 60 | "uniqueItems": true 61 | } 62 | } 63 | }, 64 | "array": { 65 | "description": "An array as defined by the Avro specification", 66 | "notes": [ "spec doesn't say whether \"items\" is required!" ], 67 | "type": "object", 68 | "required": [ "type" ], 69 | "properties": { 70 | "type": { "enum": [ "array" ] }, 71 | "items": { "$ref": "#" } 72 | } 73 | }, 74 | "map": { 75 | "description": "A map as defined by the Avro specification", 76 | "notes": [ "spec doesn't say whether \"values\" is required!" ], 77 | "type": "object", 78 | "required": [ "type" ], 79 | "properties": { 80 | "type": { "enum": [ "map" ] }, 81 | "values": { "$ref": "#" } 82 | } 83 | }, 84 | "union": { 85 | "description": "A union of schemas", 86 | "type": "array", 87 | "uniqueItems": true, 88 | "items": { 89 | "allOf": [ 90 | { "$ref": "#" }, 91 | { "not": { "$ref": "#/definitions/union" } } 92 | ] 93 | } 94 | }, 95 | "fixed": { 96 | "description": "A fixed type, as defined by the Avro specification", 97 | "type": "object", 98 | "required": [ "type", "name", "size" ], 99 | "properties": { 100 | "type": { "enum": [ "fixed" ] }, 101 | "name": { "$ref": "#/definitions/nameOrNamespace" }, 102 | "nameOrNamespace": { "$ref": "#/definitions/namespace" }, 103 | "size": { 104 | "type": "integer", 105 | "minimum": 0, 106 | "exclusiveMinimum": true 107 | }, 108 | "aliases": { "$ref": "#/definitions/aliases" } 109 | } 110 | }, 111 | "nameOrNamespace": { 112 | "description": "what a nameOrNamespace can be", 113 | "type": "string", 114 | "pattern": "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)*$" 115 | }, 116 | "aliases": { 117 | "type": "array", 118 | "minItems": 1, 119 | "uniqueItems": true, 120 | "items": {"$ref": "#/definitions/nameOrNamespace" } 121 | }, 122 | "field": { 123 | "description": "One field in a record", 124 | "type": "object", 125 | "required": [ "name", "type" ], 126 | "properties": { 127 | "name": { "$ref": "#/definitions/nameOrNamespace" }, 128 | "doc": { "type": "string" }, 129 | "type": { "$ref": "#" }, 130 | "default": { 131 | "description": "default value, depending on the type" 132 | }, 133 | "order": { 134 | "enum": [ "ascending", "descending", "ignore" ] 135 | }, 136 | "aliases": { "$ref": "#/definitions/aliases" } 137 | } 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /dot_samples/schemaout/crs.dot: -------------------------------------------------------------------------------- 1 | digraph G { 2 | fontname = "Bitstream Vera Sans" 3 | fontsize = 8 4 | 5 | node [ 6 | fontname = "Courier" 7 | fontsize = 8 8 | shape = "plaintext" 9 | ] 10 | 11 | edge [ 12 | fontname = "Bitstream Vera Sans" 13 | fontsize = 8 14 | ] 15 | 16 | "#" [ 17 | label =< 18 | 19 | 20 | 21 | 22 | 23 | linkedCrs 24 | linkedObject 25 | namedCrs 26 | 27 | ! properties 28 | ! type 29 | 30 | 31 | 32 |
#
title=crs
descr=a Coordinate Referenc...
Definitions
linkedCrs
linkedObject
namedCrs
Properties
! propertiesobject
! typestring
One Of
{properties: {type: {enum: ...
{properties: {type: {enum: ...
33 | > 34 | ] 35 | "#/definitions/namedCrs/properties/type" [ 36 | label =< 37 | 38 | 39 | 40 | 41 | 42 | 43 |
#/definitions/namedCrs/properties/type
Enum Values
name
44 | > 45 | ] 46 | "#/definitions/namedCrs/properties/properties" [ 47 | label =< 48 | 49 | 50 | 51 | 52 | 53 | ! name 54 |
#/definitions/namedCrs/properties/properties
Properties
! namestring
55 | > 56 | ] 57 | "#/definitions/namedCrs" [ 58 | label =< 59 | 60 | 61 | 62 | 63 | 64 | ? properties 65 | ? type 66 |
#/definitions/namedCrs
Properties
? properties{required: [name], addition...
? typeenum=[name]
67 | > 68 | ] 69 | "#/definitions/linkedObject" [ 70 | label =< 71 | 72 | 73 | 74 | 75 | 76 | ! href 77 | ? type 78 |
#/definitions/linkedObject
Properties
! hrefstring
? typestring
79 | > 80 | ] 81 | "#/definitions/linkedCrs/properties/type" [ 82 | label =< 83 | 84 | 85 | 86 | 87 | 88 | 89 |
#/definitions/linkedCrs/properties/type
Enum Values
link
90 | > 91 | ] 92 | "#/definitions/linkedCrs" [ 93 | label =< 94 | 95 | 96 | 97 | 98 | 99 | ? properties 100 | ? type 101 |
#/definitions/linkedCrs
Properties
? propertiesobject
? typeenum=[link]
102 | > 103 | ] 104 | "#":"0" -> "#/definitions/namedCrs":"@path"; 105 | "#":"1" -> "#/definitions/linkedCrs":"@path"; 106 | "#/definitions/namedCrs":"@properties" -> "#/definitions/namedCrs/properties/properties":"@path"; 107 | "#/definitions/namedCrs":"@type" -> "#/definitions/namedCrs/properties/type":"@path"; 108 | "#/definitions/linkedCrs":"@properties" -> "#/definitions/linkedObject":"@path"; 109 | "#/definitions/linkedCrs":"@type" -> "#/definitions/linkedCrs/properties/type":"@path"; 110 | 111 | 112 | } 113 | 114 | -------------------------------------------------------------------------------- /dot_samples/schemas/avro-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title": "avro-schema", 4 | "description": "JSON Schema for an Apache Avro schema, version 1.7.3", 5 | "oneOf": [ 6 | { "type": "string" }, 7 | { 8 | "type": "object", 9 | "required": [ "type" ], 10 | "properties": { 11 | "type": { "$ref": "#/definitions/primitiveTypes" } 12 | } 13 | }, 14 | { "$ref": "#/definitions/record" }, 15 | { "$ref": "#/definitions/enum" }, 16 | { "$ref": "#/definitions/array" }, 17 | { "$ref": "#/definitions/map" }, 18 | { "$ref": "#/definitions/union" }, 19 | { "$ref": "#/definitions/fixed" } 20 | ], 21 | "definitions": { 22 | "primitiveTypes": { 23 | "description": "One primitive type", 24 | "enum": [ "null", "boolean", "int", "long", "float", "double", "bytes", "string" ] 25 | }, 26 | "record": { 27 | "description": "A record", 28 | "type": "object", 29 | "required": [ "type", "name", "fields" ], 30 | "properties": { 31 | "type": { "enum": [ "record" ] }, 32 | "name": { "$ref": "#/definitions/name" }, 33 | "nameOrNamespace": { "$ref": "#/definitions/nameOrNamespace" }, 34 | "doc": { "type": "string" }, 35 | "aliases": { "$ref": "#/definitions/aliases" }, 36 | "fields": { 37 | "type": "array", 38 | "items": { "$ref": "#/definitions/field" } 39 | } 40 | } 41 | }, 42 | "enum": { 43 | "description": "an enum as defined by the Avro specification", 44 | "type": "object", 45 | "required": [ "type", "name", "symbols" ], 46 | "properties": { 47 | "type": { "enum": [ "enum" ] }, 48 | "name": { "$ref": "#/definitions/name" }, 49 | "nameOrNamespace": { "$ref": "#/definitions/nameOrNamespace" }, 50 | "aliases": { "$ref": "#/definitions/aliases" }, 51 | "doc": { "type": "string" }, 52 | "symbols": { 53 | "type": "array", 54 | "minItems": 1, 55 | "items": { 56 | "type": "string", 57 | "minLength": 1, 58 | "pattern": "^(?![_\\d])\\w+$" 59 | }, 60 | "uniqueItems": true 61 | } 62 | } 63 | }, 64 | "array": { 65 | "description": "An array as defined by the Avro specification", 66 | "notes": [ "spec doesn't say whether \"items\" is required!" ], 67 | "type": "object", 68 | "required": [ "type" ], 69 | "properties": { 70 | "type": { "enum": [ "array" ] }, 71 | "items": { "$ref": "#" } 72 | } 73 | }, 74 | "map": { 75 | "description": "A map as defined by the Avro specification", 76 | "notes": [ "spec doesn't say whether \"values\" is required!" ], 77 | "type": "object", 78 | "required": [ "type" ], 79 | "properties": { 80 | "type": { "enum": [ "map" ] }, 81 | "values": { "$ref": "#" } 82 | } 83 | }, 84 | "union": { 85 | "description": "A union of schemas", 86 | "type": "array", 87 | "uniqueItems": true, 88 | "items": { 89 | "allOf": [ 90 | { "$ref": "#" }, 91 | { "not": { "$ref": "#/definitions/union" } } 92 | ] 93 | } 94 | }, 95 | "fixed": { 96 | "description": "A fixed type, as defined by the Avro specification", 97 | "type": "object", 98 | "required": [ "type", "name", "size" ], 99 | "properties": { 100 | "type": { "enum": [ "fixed" ] }, 101 | "name": { "$ref": "#/definitions/name" }, 102 | "nameOrNamespace": { "$ref": "#/definitions/nameOrNamespace" }, 103 | "size": { 104 | "type": "integer", 105 | "minimum": 0, 106 | "exclusiveMinimum": true 107 | }, 108 | "aliases": { "$ref": "#/definitions/aliases" } 109 | } 110 | }, 111 | "name": { 112 | "description": "what a name can be", 113 | "type": "string", 114 | "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" 115 | }, 116 | "nameOrNamespace": { 117 | "description": "what a nameOrNamespace can be", 118 | "type": "string", 119 | "pattern": "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)*$" 120 | }, 121 | "aliases": { 122 | "type": "array", 123 | "minItems": 1, 124 | "uniqueItems": true, 125 | "items": {"$ref": "#/definitions/nameOrNamespace" } 126 | }, 127 | "field": { 128 | "description": "One field in a record", 129 | "type": "object", 130 | "required": [ "name", "type" ], 131 | "properties": { 132 | "name": { "$ref": "#/definitions/nameOrNamespace" }, 133 | "doc": { "type": "string" }, 134 | "type": { "$ref": "#" }, 135 | "default": { 136 | "description": "default value, depending on the type" 137 | }, 138 | "order": { 139 | "enum": [ "ascending", "descending", "ignore" ] 140 | }, 141 | "aliases": { "$ref": "#/definitions/aliases" } 142 | } 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Json Schema 2 | 3 | A *dart:io* dependent library for validating json instances against json schema (version Draft 04) 4 | 5 | ![Build Status](https://travis-ci.org/patefacio/json_schema.svg) 6 | 7 | 8 | # How To Validate 9 | 10 | To validate instances against a schema first create the schema, then 11 | call validate on it with an json instance. This can be done with an 12 | url: 13 | 14 | ### Example 1 15 | 16 | String url = "http://json-schema.org/draft-04/schema"; 17 | Schema.createSchemaFromUrl(url) 18 | .then((schema) { 19 | print('Does schema validate itself? ${schema.validate(schema.schemaMap)}'); 20 | }); 21 | 22 | In this example a schema is created from the url and its stored 23 | contents are validated against itself. Since the referenced schema 24 | is the schema for schemas and the instance is, of course, a schema, 25 | the result prints true. 26 | 27 | ### Example 2 28 | 29 | An url can point to a local file, either of format 30 | _file:///absolute\_path\_to/schema.json_ or _subfolder/schema.json_ 31 | where _subfolder_ is a subfolder of current working directory. An 32 | example of this can be found in 33 | _example/from\_url/validate\_instance\_from\_url.dart_ 34 | 35 | url = "grades_schema.json"; 36 | Schema.createSchemaFromUrl(url) 37 | .then((schema) { 38 | var grades = JSON.parse(''' 39 | { 40 | "semesters": [ 41 | { 42 | "semester": 1, 43 | "grades": [ 44 | { 45 | "type": "homework", 46 | "date": "09/27/2013", 47 | "grade": 100, 48 | "avg": 93, 49 | "std": 8 50 | }, 51 | { 52 | "type": "homework", 53 | "date": "09/28/2013", 54 | "grade": 100, 55 | "avg": 60, 56 | "std": 25 57 | } 58 | ] 59 | } 60 | ] 61 | }'''); 62 | 63 | print('''Does grades schema validate $grades 64 | ${schema.validate(grades)}'''); 65 | 66 | In this example the schema is read from file _grades\_schema.json_ 67 | in the current directory and a valid instance is submitted for 68 | validation (in the string of the print statement). This example also 69 | prints true. 70 | 71 | ### Example 3 72 | 73 | A schema can be created with a Map that is either hand-crafted or 74 | the result of a call to json parse. 75 | 76 | ////////////////////////////////////////////////////////////////////// 77 | // Define schema in code 78 | ////////////////////////////////////////////////////////////////////// 79 | var mustBeIntegerSchema = { 80 | "type" : "integer" 81 | }; 82 | 83 | var n = 3; 84 | var decimals = 3.14; 85 | var str = 'hi'; 86 | 87 | Schema.createSchema(mustBeIntegerSchema) 88 | .then((schema) { 89 | print('$n => ${schema.validate(n)}'); 90 | print('$decimals => ${schema.validate(decimals)}'); 91 | print('$str => ${schema.validate(str)}'); 92 | }); 93 | 94 | This example creates a schema requiring the type be integer. It then 95 | tests against three instances with the following results: 96 | 97 | 3 => true 98 | 3.14 => false 99 | hi => false 100 | 101 | # How To Use Schema Information 102 | 103 | Schema information can be used for validation; but it can also be a 104 | valuable source of information about the structure of data. The 105 | Schema class provided here works by fully parsing the schema first, 106 | which itself must be valid on all paths within the schema. The only 107 | invalid content of a provided schema are _free-form properties_ 108 | containing schema that are not referenced. Accessors are provided 109 | for the meta-data associated with a schema, so tools can do *stuff* 110 | with it. 111 | 112 | One example use is the _schemadot_ program included in the _bin_ 113 | folder which takes schema as input and outputs a _Graphviz_ _dot_ 114 | file, providing a picture of the schema. This does not provide all 115 | information of the schema, and is a work in progress - but it can be 116 | useful to *see* what a schema is. 117 | 118 | For example, the grades_schema.json is: 119 | 120 | { 121 | "$schema": "http://json-schema.org/draft-04/schema#", 122 | "title" : "Grade Tracker", 123 | "type" : "object", 124 | "additionalProperties" : false, 125 | "properties" : { 126 | "semesters" : { 127 | "type" : "array", 128 | "items" : { 129 | "type" : "object", 130 | "additionalProperties" : false, 131 | "properties" : { 132 | "semester": { "type" : "integer" }, 133 | "grades" : { 134 | "type" : "array", 135 | "items" : { 136 | "type" : "object", 137 | "additionalProperties" : false, 138 | "required" : [ "date", "type", "grade", "std" ], 139 | "properties" : { 140 | "date" : { "type" : "string"}, 141 | "type" : { "enum" : [ "homework", "quiz", "test", "final_exam" ] }, 142 | "grade" : { "type" : "number"}, 143 | "std" : { 144 | "oneOf" : [ 145 | {"type" : "number"}, 146 | {"type" : "null"} 147 | ] 148 | }, 149 | "avg" : { 150 | "oneOf" : [ 151 | {"type" : "number"}, 152 | {"type" : "null"} 153 | ] 154 | } 155 | } 156 | } 157 | } 158 | } 159 | } 160 | } 161 | } 162 | } 163 | 164 | And the generated image is: 165 | 166 | ![Grades!](https://raw.github.com/patefacio/json_schema/master/example/from_url/grades_schema.png) 167 | 168 | For more detailed image open link: 169 | Grade example schema diagram 171 | 172 | # TODOS 173 | 174 | * Add a remote ref test that does not require files vended from local host 175 | * Add support for optional tests: format 176 | --------------------------------------------------------------------------------