git.iko.soy/typeable/hjsonschema
on cd19d79 help sign in
178 files changed+2831−12925
since splitsnapshots
unifiedsplit
.gitignore+1 .gitmodules+3 .travis.yml+53−67 JSON-Schema-Test-Suite+1 JSON-Schema-Test-Suite/.gitignore−1 JSON-Schema-Test-Suite/.travis.yml−9 JSON-Schema-Test-Suite/LICENSE−19 JSON-Schema-Test-Suite/README.md−169 JSON-Schema-Test-Suite/bin/jsonschema_suite−258 JSON-Schema-Test-Suite/index.js−32 JSON-Schema-Test-Suite/package.json−28 JSON-Schema-Test-Suite/remotes/folder/folderInteger.json−3 JSON-Schema-Test-Suite/remotes/integer.json−3 JSON-Schema-Test-Suite/remotes/name.json−11 JSON-Schema-Test-Suite/remotes/subSchemas.json−8 JSON-Schema-Test-Suite/shell.nix−8 JSON-Schema-Test-Suite/test-schema.json−28 JSON-Schema-Test-Suite/tests/draft3/additionalItems.json−82 JSON-Schema-Test-Suite/tests/draft3/additionalProperties.json−88 JSON-Schema-Test-Suite/tests/draft3/default.json−49 JSON-Schema-Test-Suite/tests/draft3/dependencies.json−108 JSON-Schema-Test-Suite/tests/draft3/disallow.json−80 JSON-Schema-Test-Suite/tests/draft3/divisibleBy.json−60 JSON-Schema-Test-Suite/tests/draft3/enum.json−71 JSON-Schema-Test-Suite/tests/draft3/extends.json−94 JSON-Schema-Test-Suite/tests/draft3/items.json−46 JSON-Schema-Test-Suite/tests/draft3/maxItems.json−28 JSON-Schema-Test-Suite/tests/draft3/maxLength.json−33 JSON-Schema-Test-Suite/tests/draft3/maximum.json−42 JSON-Schema-Test-Suite/tests/draft3/minItems.json−28 JSON-Schema-Test-Suite/tests/draft3/minLength.json−33 JSON-Schema-Test-Suite/tests/draft3/minimum.json−42 JSON-Schema-Test-Suite/tests/draft3/optional/bignum.json−107 JSON-Schema-Test-Suite/tests/draft3/optional/format.json−222 JSON-Schema-Test-Suite/tests/draft3/optional/jsregex.json−18 JSON-Schema-Test-Suite/tests/draft3/optional/zeroTerminatedFloats.json−15 JSON-Schema-Test-Suite/tests/draft3/pattern.json−34 JSON-Schema-Test-Suite/tests/draft3/patternProperties.json−110 JSON-Schema-Test-Suite/tests/draft3/properties.json−92 JSON-Schema-Test-Suite/tests/draft3/ref.json−192 JSON-Schema-Test-Suite/tests/draft3/refRemote.json−74 JSON-Schema-Test-Suite/tests/draft3/required.json−53 JSON-Schema-Test-Suite/tests/draft3/type.json−489 JSON-Schema-Test-Suite/tests/draft3/uniqueItems.json−79 JSON-Schema-Test-Suite/tests/draft4/additionalItems.json−87 JSON-Schema-Test-Suite/tests/draft4/additionalProperties.json−88 JSON-Schema-Test-Suite/tests/draft4/allOf.json−112 JSON-Schema-Test-Suite/tests/draft4/anyOf.json−68 JSON-Schema-Test-Suite/tests/draft4/default.json−49 JSON-Schema-Test-Suite/tests/draft4/definitions.json−32 JSON-Schema-Test-Suite/tests/draft4/dependencies.json−113 JSON-Schema-Test-Suite/tests/draft4/enum.json−72 JSON-Schema-Test-Suite/tests/draft4/items.json−78 JSON-Schema-Test-Suite/tests/draft4/maxItems.json−28 JSON-Schema-Test-Suite/tests/draft4/maxLength.json−33 JSON-Schema-Test-Suite/tests/draft4/maxProperties.json−28 JSON-Schema-Test-Suite/tests/draft4/maximum.json−47 JSON-Schema-Test-Suite/tests/draft4/minItems.json−28 JSON-Schema-Test-Suite/tests/draft4/minLength.json−33 JSON-Schema-Test-Suite/tests/draft4/minProperties.json−28 JSON-Schema-Test-Suite/tests/draft4/minimum.json−47 JSON-Schema-Test-Suite/tests/draft4/multipleOf.json−60 JSON-Schema-Test-Suite/tests/draft4/not.json−96 JSON-Schema-Test-Suite/tests/draft4/oneOf.json−68 JSON-Schema-Test-Suite/tests/draft4/optional/bignum.json−107 JSON-Schema-Test-Suite/tests/draft4/optional/ecmascript-regex.json−13 JSON-Schema-Test-Suite/tests/draft4/optional/format.json−148 JSON-Schema-Test-Suite/tests/draft4/optional/zeroTerminatedFloats.json−15 JSON-Schema-Test-Suite/tests/draft4/pattern.json−34 JSON-Schema-Test-Suite/tests/draft4/patternProperties.json−110 JSON-Schema-Test-Suite/tests/draft4/properties.json−92 JSON-Schema-Test-Suite/tests/draft4/ref.json−298 JSON-Schema-Test-Suite/tests/draft4/refRemote.json−171 JSON-Schema-Test-Suite/tests/draft4/required.json−44 JSON-Schema-Test-Suite/tests/draft4/type.json−345 JSON-Schema-Test-Suite/tests/draft4/uniqueItems.json−79 JSON-Schema-Test-Suite/tests/draft6/additionalItems.json−87 JSON-Schema-Test-Suite/tests/draft6/additionalProperties.json−88 JSON-Schema-Test-Suite/tests/draft6/allOf.json−145 JSON-Schema-Test-Suite/tests/draft6/anyOf.json−101 JSON-Schema-Test-Suite/tests/draft6/boolean_schema.json−104 JSON-Schema-Test-Suite/tests/draft6/const.json−65 JSON-Schema-Test-Suite/tests/draft6/contains.json−95 JSON-Schema-Test-Suite/tests/draft6/default.json−49 JSON-Schema-Test-Suite/tests/draft6/definitions.json−32 JSON-Schema-Test-Suite/tests/draft6/dependencies.json−162 JSON-Schema-Test-Suite/tests/draft6/enum.json−72 JSON-Schema-Test-Suite/tests/draft6/exclusiveMaximum.json−30 JSON-Schema-Test-Suite/tests/draft6/exclusiveMinimum.json−30 JSON-Schema-Test-Suite/tests/draft6/items.json−133 JSON-Schema-Test-Suite/tests/draft6/maxItems.json−28 JSON-Schema-Test-Suite/tests/draft6/maxLength.json−33 JSON-Schema-Test-Suite/tests/draft6/maxProperties.json−28 JSON-Schema-Test-Suite/tests/draft6/maximum.json−28 JSON-Schema-Test-Suite/tests/draft6/minItems.json−28 JSON-Schema-Test-Suite/tests/draft6/minLength.json−33 JSON-Schema-Test-Suite/tests/draft6/minProperties.json−28 JSON-Schema-Test-Suite/tests/draft6/minimum.json−28 JSON-Schema-Test-Suite/tests/draft6/multipleOf.json−60 JSON-Schema-Test-Suite/tests/draft6/not.json−117 JSON-Schema-Test-Suite/tests/draft6/oneOf.json−112 JSON-Schema-Test-Suite/tests/draft6/optional/bignum.json−105 JSON-Schema-Test-Suite/tests/draft6/optional/ecmascript-regex.json−13 JSON-Schema-Test-Suite/tests/draft6/optional/format.json−148 JSON-Schema-Test-Suite/tests/draft6/optional/zeroTerminatedFloats.json−15 JSON-Schema-Test-Suite/tests/draft6/pattern.json−34 JSON-Schema-Test-Suite/tests/draft6/patternProperties.json−141 JSON-Schema-Test-Suite/tests/draft6/properties.json−123 JSON-Schema-Test-Suite/tests/draft6/propertyNames.json−68 JSON-Schema-Test-Suite/tests/draft6/ref.json−332 JSON-Schema-Test-Suite/tests/draft6/refRemote.json−171 JSON-Schema-Test-Suite/tests/draft6/required.json−60 JSON-Schema-Test-Suite/tests/draft6/type.json−345 JSON-Schema-Test-Suite/tests/draft6/uniqueItems.json−79 JSON-Schema-Test-Suite/tox.ini−8 README.md+45−13 changelog.md−209 changelog.txt+65 examples/AlternateSchema.hs−200 examples/CustomSchema.hs+68 examples/Main.hs+19 examples/PrettyShowFailure.hs+58 examples/Simple.hs−37 examples/Standard.hs+49 examples/TwoStep.hs−48 examples/json/start.json−3 examples/json/unique.json−3 hjsonschema.cabal+124−155 logo.jpg shell.nix−15 src/Data/JsonSchema/Draft4.hs+132 src/Data/JsonSchema/Draft4/Failure.hs+68 src/Data/JsonSchema/Draft4/Internal.hs+280 src/Data/JsonSchema/Draft4/Schema.hs+334 src/Data/JsonSchema/Fetch.hs+173 src/Data/Validator/Draft4.hs+8 src/Data/Validator/Draft4/Any.hs+178 src/Data/Validator/Draft4/Array.hs+168 src/Data/Validator/Draft4/Number.hs+51 src/Data/Validator/Draft4/Object.hs+147 src/Data/Validator/Draft4/Object/Properties.hs+190 src/Data/Validator/Draft4/String.hs+32 src/Data/Validator/Failure.hs+42 src/Data/Validator/Reference.hs+91 src/Data/Validator/Utils.hs+122 src/Import.hs+9−16 src/JSONSchema/Draft4.hs−186 src/JSONSchema/Draft4/Failure.hs−58 src/JSONSchema/Draft4/Schema.hs−341 src/JSONSchema/Draft4/Spec.hs−150 src/JSONSchema/Fetch.hs−175 src/JSONSchema/Types.hs−35 src/JSONSchema/Validator/Draft4.hs−242 src/JSONSchema/Validator/Draft4/Any.hs−509 src/JSONSchema/Validator/Draft4/Array.hs−225 src/JSONSchema/Validator/Draft4/Number.hs−83 src/JSONSchema/Validator/Draft4/Object.hs−182 src/JSONSchema/Validator/Draft4/Object/Properties.hs−209 src/JSONSchema/Validator/Draft4/String.hs−78 src/JSONSchema/Validator/Reference.hs−71 src/JSONSchema/Validator/Types.hs−22 src/JSONSchema/Validator/Utils.hs−119 stack.yaml−2 test/Local.hs−98 test/Local/Failure.hs−105 test/Local/Reference.hs−36 test/Local/Validation.hs−70 test/Remote.hs−57 test/Shared.hs−134 test/supplement/recurse.json−17 tests/Local.hs+34 tests/Local/Failure.hs+55 tests/Local/Filesystem.hs+55 tests/Local/Reference.hs+51 test/Local/schema-with-ref.json → tests/Local/schema-with-ref.json test/Local/schema.json → tests/Local/schema.json tests/Remote.hs+26 tests/Shared.hs+99
.gitignorenew file+1
@@ -0,0 +1 @@
1+stack.yaml
.gitmodulesnew file+3
@@ -0,0 +1,3 @@
1+[submodule "JSON-Schema-Test-Suite"]
2+ path = JSON-Schema-Test-Suite
3+ url = https://github.com/json-schema/JSON-Schema-Test-Suite
.travis.yml+53−67
@@ -1,95 +1,81 @@
1−# This Travis job script has been generated by a script via
2−#
3−# make_travis_yml_2.hs 'hjsonschema.cabal'
4−#
5−# For more information, see https://github.com/hvr/multi-ghc-travis
1+# This file has been generated -- see https://github.com/hvr/multi-ghc-travis
62#
3+# Manually modified to remove cabal check. I don't want a description field.
4+
75language: c
86sudo: false
97
10−git:
11− submodules: false # whether to recursively clone submodules
12−
138cache:
149 directories:
10+ - $HOME/.cabsnap
1511 - $HOME/.cabal/packages
16− - $HOME/.cabal/store
1712
1813before_cache:
1914 - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log
20− # remove files that are regenerated by 'cabal update'
21− - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.*
22− - rm -fv $HOME/.cabal/packages/hackage.haskell.org/*.json
23− - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.cache
24− - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar
25− - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar.idx
15+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar
2616
2717matrix:
2818 include:
29− - compiler: "ghc-8.0.2"
30− # env: TEST=--disable-tests BENCH=--disable-benchmarks
31− addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.0.2], sources: [hvr-ghc]}}
32− - compiler: "ghc-8.2.2"
33− # env: TEST=--disable-tests BENCH=--disable-benchmarks
34− addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.2.2], sources: [hvr-ghc]}}
35− - compiler: "ghc-8.4.1"
36− # env: TEST=--disable-tests BENCH=--disable-benchmarks
37− addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.4.1], sources: [hvr-ghc]}}
19+ - env: CABALVER=1.18 GHCVER=7.8.4
20+ compiler: ": #GHC 7.8.4"
21+ addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4], sources: [hvr-ghc]}}
22+ - env: CABALVER=1.22 GHCVER=7.10.2
23+ compiler: ": #GHC 7.10.2"
24+ addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.2], sources: [hvr-ghc]}}
3825
3926before_install:
40− - HC=${CC}
41− - HCPKG=${HC/ghc/ghc-pkg}
4227 - unset CC
43− - PATH=/opt/ghc/bin:/opt/ghc-ppa-tools/bin:$PATH
44− - PKGNAME='hjsonschema'
28+ - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
4529
4630install:
4731 - cabal --version
48− - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"
49− - BENCH=${BENCH---enable-benchmarks}
50− - TEST=${TEST---enable-tests}
51− - HADDOCK=${HADDOCK-true}
52− - INSTALLED=${INSTALLED-true}
32+ - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
33+ - if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ];
34+ then
35+ zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz >
36+ $HOME/.cabal/packages/hackage.haskell.org/00-index.tar;
37+ fi
5338 - travis_retry cabal update -v
54− - sed -i.bak 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config
55− - rm -fv cabal.project.local
56− - "echo 'packages: .' > cabal.project"
57− - rm -f cabal.project.freeze
58− - cabal new-build -w ${HC} ${TEST} ${BENCH} --dep -j2 all
59− - cabal new-build -w ${HC} --disable-tests --disable-benchmarks --dep -j2 all
39+ - sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config
40+ - cabal install --only-dependencies --enable-tests --enable-benchmarks --dry -v > installplan.txt
41+ - sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt
42+
43+# check whether current requested install-plan matches cached package-db snapshot
44+ - if diff -u installplan.txt $HOME/.cabsnap/installplan.txt;
45+ then
46+ echo "cabal build-cache HIT";
47+ rm -rfv .ghc;
48+ cp -a $HOME/.cabsnap/ghc $HOME/.ghc;
49+ cp -a $HOME/.cabsnap/lib $HOME/.cabsnap/share $HOME/.cabsnap/bin $HOME/.cabal/;
50+ else
51+ echo "cabal build-cache MISS";
52+ rm -rf $HOME/.cabsnap;
53+ mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin;
54+ cabal install --only-dependencies --enable-tests --enable-benchmarks;
55+ fi
56+
57+# snapshot package-db on cache miss
58+ - if [ ! -d $HOME/.cabsnap ];
59+ then
60+ echo "snapshotting package-db to build-cache";
61+ mkdir $HOME/.cabsnap;
62+ cp -a $HOME/.ghc $HOME/.cabsnap/ghc;
63+ cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/;
64+ fi
6065
6166# Here starts the actual work to be performed for the package under test;
6267# any command which exits with a non-zero exit code causes the build to fail.
6368script:
6469 - if [ -f configure.ac ]; then autoreconf -i; fi
65− - rm -rf .ghc.environment.* dist/
66− - cabal sdist # test that a source-distribution can be generated
67− - cd dist/
68− - SRCTAR=(${PKGNAME}-*.tar.gz)
69− - SRC_BASENAME="${SRCTAR/%.tar.gz}"
70− - tar -xvf "./$SRC_BASENAME.tar.gz"
71− - cd "$SRC_BASENAME/"
72−## from here on, CWD is inside the extracted source-tarball
73− - rm -fv cabal.project.local
74− - "echo 'packages: .' > cabal.project"
75− # this builds all libraries and executables (without tests/benchmarks)
76− - rm -f cabal.project.freeze
77− - cabal new-build -w ${HC} --disable-tests --disable-benchmarks all
78− # this builds all libraries and executables (including tests/benchmarks)
79− # - rm -rf ./dist-newstyle
80−
81− # Build with installed constraints for packages in global-db
82− - if $INSTALLED; then
83− echo cabal new-build -w ${HC} --disable-tests --disable-benchmarks $(${HCPKG} list --global --simple-output --names-only | sed 's/\([a-zA-Z0-9-]\{1,\}\) */--constraint="\1 installed" /g') all | sh;
84− else echo "Not building with installed constraints"; fi
85−
86− # build & run tests, build benchmarks
87− - cabal new-build -w ${HC} ${TEST} ${BENCH} all
88− - if [ "x$TEST" = "x--enable-tests" ]; then cabal new-test -w ${HC} ${TEST} all; fi
70+ - cabal configure --enable-tests --enable-benchmarks -v2 # -v2 provides useful information for debugging
71+ - cabal build # this builds all libraries and executables (including tests/benchmarks)
72+ - cabal test
73+ - cabal sdist # tests that a source-distribution can be generated
8974
90− # haddock
91− - rm -rf ./dist-newstyle
92− - if $HADDOCK; then cabal new-haddock -w ${HC} --disable-tests --disable-benchmarks all; else echo "Skipping haddock generation";fi
75+# Check that the resulting source distribution can be built & installed.
76+# If there are no other `.tar.gz` files in `dist`, this can be even simpler:
77+# `cabal install --force-reinstalls dist/*-*.tar.gz`
78+ - SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz &&
79+ (cd dist && cabal install --force-reinstalls "$SRC_TGZ")
9380
94−# REGENDATA ["hjsonschema.cabal"]
9581# EOF
JSON-Schema-Test-Suitenew file+1

Submodule changed.

JSON-Schema-Test-Suite/.gitignoredeleted−1
@@ -1 +0,0 @@
1−TODO
JSON-Schema-Test-Suite/.travis.ymldeleted−9
@@ -1,9 +0,0 @@
1−language: python
2−python: "2.7"
3−node_js: "6"
4−install:
5− - pip install tox
6− - npm install
7−script:
8− - tox
9− - npm test
JSON-Schema-Test-Suite/LICENSEdeleted−19
@@ -1,19 +0,0 @@
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.
JSON-Schema-Test-Suite/README.mddeleted−169
@@ -1,169 +0,0 @@
1−JSON Schema Test Suite [![Build Status](https://travis-ci.org/json-schema-org/JSON-Schema-Test-Suite.svg?branch=master)](https://travis-ci.org/json-schema-org/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−### Coffeescript ###
64−
65−* [jsck](https://github.com/pandastrike/jsck)
66−
67−### C++ ###
68−
69−* [Modern C++ JSON schema validator](https://github.com/pboettch/json-schema-validator)
70−
71−### Dart ###
72−
73−* [json_schema](https://github.com/patefacio/json_schema)
74−
75−### Elixir ###
76−
77−* [ex_json_schema](https://github.com/jonasschmidt/ex_json_schema)
78−
79−### Erlang ###
80−
81−* [jesse](https://github.com/klarna/jesse)
82−
83−### Go ###
84−
85−* [gojsonschema](https://github.com/sigu-399/gojsonschema)
86−* [validate-json](https://github.com/cesanta/validate-json)
87−
88−### Haskell ###
89−
90−* [aeson-schema](https://github.com/timjb/aeson-schema)
91−* [hjsonschema](https://github.com/seagreen/hjsonschema)
92−
93−### Java ###
94−
95−* [json-schema-validator](https://github.com/daveclayton/json-schema-validator)
96−* [everit-org/json-schema](https://github.com/everit-org/json-schema)
97−* [networknt/json-schema-validator](https://github.com/networknt/json-schema-validator)
98−
99−### JavaScript ###
100−
101−* [json-schema-benchmark](https://github.com/Muscula/json-schema-benchmark)
102−* [direct-schema](https://github.com/IreneKnapp/direct-schema)
103−* [is-my-json-valid](https://github.com/mafintosh/is-my-json-valid)
104−* [jassi](https://github.com/iclanzan/jassi)
105−* [JaySchema](https://github.com/natesilva/jayschema)
106−* [json-schema-valid](https://github.com/ericgj/json-schema-valid)
107−* [Jsonary](https://github.com/jsonary-js/jsonary)
108−* [jsonschema](https://github.com/tdegrunt/jsonschema)
109−* [request-validator](https://github.com/bugventure/request-validator)
110−* [skeemas](https://github.com/Prestaul/skeemas)
111−* [tv4](https://github.com/geraintluff/tv4)
112−* [z-schema](https://github.com/zaggino/z-schema)
113−* [jsen](https://github.com/bugventure/jsen)
114−* [ajv](https://github.com/epoberezkin/ajv)
115−* [djv](https://github.com/korzio/djv)
116−
117−### Node.js ###
118−
119−The JSON Schema Test Suite is also available as an
120−[npm](https://www.npmjs.com/package/json-schema-test-suite) package.
121−Node-specific support is maintained on the [node branch](https://github.com/json-schema-org/JSON-Schema-Test-Suite/tree/node).
122−See [NODE-README.md](https://github.com/json-schema-org/JSON-Schema-Test-Suite/blob/node/NODE-README.md)
123−for more information.
124−
125−### .NET ###
126−
127−* [Newtonsoft.Json.Schema](https://github.com/JamesNK/Newtonsoft.Json.Schema)
128−* [Manatee.Json](https://github.com/gregsdennis/Manatee.Json)
129−
130−### PHP ###
131−
132−* [json-schema](https://github.com/justinrainbow/json-schema)
133−* [json-guard](https://github.com/thephpleague/json-guard)
134−
135−### Python ###
136−
137−* [jsonschema](https://github.com/Julian/jsonschema)
138−
139−### Ruby ###
140−
141−* [json-schema](https://github.com/hoxworth/json-schema)
142−
143−### Rust ###
144−
145−* [valico](https://github.com/rustless/valico)
146−
147−### Swift ###
148−
149−* [JSONSchema](https://github.com/kylef/JSONSchema.swift)
150−
151−### Clojure ###
152−
153−* [json-schema](https://github.com/tatut/json-schema)
154−
155−### PostgreSQL ###
156−
157−* [postgres-json-schema](https://github.com/gavinwahl/postgres-json-schema)
158−
159−If you use it as well, please fork and send a pull request adding yourself to
160−the list :).
161−
162−Contributing
163−------------
164−
165−If you see something missing or incorrect, a pull request is most welcome!
166−
167−There are some sanity checks in place for testing the test suite. You can run
168−them with `bin/jsonschema_suite check && npm test` or `tox && npm test`. They will be run automatically by
169−[Travis CI](https://travis-ci.org/) as well.
JSON-Schema-Test-Suite/bin/jsonschema_suitedeleted−258
@@ -1,258 +0,0 @@
1−#! /usr/bin/env python
2−from __future__ import print_function
3−import sys
4−import textwrap
5−
6−try:
7− import argparse
8−except ImportError:
9− print(textwrap.dedent("""
10− The argparse library could not be imported. jsonschema_suite requires
11− either Python 2.7 or for you to install argparse. You can do so by
12− running `pip install argparse`, `easy_install argparse` or by
13− downloading argparse and running `python2.6 setup.py install`.
14−
15− See https://pypi.python.org/pypi/argparse for details.
16− """.strip("\n")))
17− sys.exit(1)
18−
19−import errno
20−import fnmatch
21−import json
22−import os
23−import random
24−import shutil
25−import unittest
26−import warnings
27−
28−if getattr(unittest, "skipIf", None) is None:
29− unittest.skipIf = lambda cond, msg : lambda fn : fn
30−
31−try:
32− import jsonschema
33−except ImportError:
34− jsonschema = None
35−else:
36− validators = getattr(
37− jsonschema.validators, "validators", jsonschema.validators
38− )
39−
40−
41−ROOT_DIR = os.path.join(
42− os.path.dirname(__file__), os.pardir).rstrip("__pycache__")
43−SUITE_ROOT_DIR = os.path.join(ROOT_DIR, "tests")
44−
45−REMOTES = {
46− "integer.json": {"type": "integer"},
47− "subSchemas.json": {
48− "integer": {"type": "integer"},
49− "refToInteger": {"$ref": "#/integer"},
50− },
51− "folder/folderInteger.json": {"type": "integer"}
52−}
53−REMOTES_DIR = os.path.join(ROOT_DIR, "remotes")
54−
55−with open(os.path.join(ROOT_DIR, "test-schema.json")) as schema:
56− TESTSUITE_SCHEMA = json.load(schema)
57−
58−def files(paths):
59− for path in paths:
60− with open(path) as test_file:
61− yield json.load(test_file)
62−
63−
64−def groups(paths):
65− for test_file in files(paths):
66− for group in test_file:
67− yield group
68−
69−
70−def cases(paths):
71− for test_group in groups(paths):
72− for test in test_group["tests"]:
73− test["schema"] = test_group["schema"]
74− yield test
75−
76−
77−def collect(root_dir):
78− for root, dirs, files in os.walk(root_dir):
79− for filename in fnmatch.filter(files, "*.json"):
80− yield os.path.join(root, filename)
81−
82−
83−class SanityTests(unittest.TestCase):
84− @classmethod
85− def setUpClass(cls):
86− print("Looking for tests in %s" % SUITE_ROOT_DIR)
87− cls.test_files = list(collect(SUITE_ROOT_DIR))
88− print("Found %s test files" % len(cls.test_files))
89− assert cls.test_files, "Didn't find the test files!"
90−
91− def test_all_files_are_valid_json(self):
92− for path in self.test_files:
93− with open(path) as test_file:
94− try:
95− json.load(test_file)
96− except ValueError as error:
97− self.fail("%s contains invalid JSON (%s)" % (path, error))
98−
99− def test_all_descriptions_have_reasonable_length(self):
100− for case in cases(self.test_files):
101− descript = case["description"]
102− self.assertLess(
103− len(descript),
104− 60,
105− "%r is too long! (keep it to less than 60 chars)" % (descript,)
106− )
107−
108− def test_all_descriptions_are_unique(self):
109− for group in groups(self.test_files):
110− descriptions = set(test["description"] for test in group["tests"])
111− self.assertEqual(
112− len(descriptions),
113− len(group["tests"]),
114− "%r contains a duplicate description" % (group,)
115− )
116−
117− @unittest.skipIf(jsonschema is None, "Validation library not present!")
118− def test_all_schemas_are_valid(self):
119− for schema in os.listdir(SUITE_ROOT_DIR):
120− schema_validator = validators.get(schema)
121− if schema_validator is not None:
122− test_files = collect(os.path.join(SUITE_ROOT_DIR, schema))
123− for case in cases(test_files):
124− try:
125− schema_validator.check_schema(case["schema"])
126− except jsonschema.SchemaError as error:
127− self.fail("%s contains an invalid schema (%s)" %
128− (case, error))
129− else:
130− warnings.warn("No schema validator for %s" % schema)
131−
132− @unittest.skipIf(jsonschema is None, "Validation library not present!")
133− def test_suites_are_valid(self):
134− validator = jsonschema.Draft3Validator(TESTSUITE_SCHEMA)
135− for tests in files(self.test_files):
136− try:
137− validator.validate(tests)
138− except jsonschema.ValidationError as error:
139− self.fail(str(error))
140−
141− def test_remote_schemas_are_updated(self):
142− for url, schema in REMOTES.items():
143− filepath = os.path.join(REMOTES_DIR, url)
144− with open(filepath) as schema_file:
145− self.assertEqual(json.load(schema_file), schema)
146−
147−
148−def main(arguments):
149− if arguments.command == "check":
150− suite = unittest.TestLoader().loadTestsFromTestCase(SanityTests)
151− result = unittest.TextTestRunner(verbosity=2).run(suite)
152− sys.exit(not result.wasSuccessful())
153− elif arguments.command == "flatten":
154− selected_cases = [case for case in cases(collect(arguments.version))]
155−
156− if arguments.randomize:
157− random.shuffle(selected_cases)
158−
159− json.dump(selected_cases, sys.stdout, indent=4, sort_keys=True)
160− elif arguments.command == "remotes":
161− json.dump(REMOTES, sys.stdout, indent=4, sort_keys=True)
162− elif arguments.command == "dump_remotes":
163− if arguments.update:
164− shutil.rmtree(arguments.out_dir, ignore_errors=True)
165−
166− try:
167− os.makedirs(arguments.out_dir)
168− except OSError as e:
169− if e.errno == errno.EEXIST:
170− print("%s already exists. Aborting." % arguments.out_dir)
171− sys.exit(1)
172− raise
173−
174− for url, schema in REMOTES.items():
175− filepath = os.path.join(arguments.out_dir, url)
176−
177− try:
178− os.makedirs(os.path.dirname(filepath))
179− except OSError as e:
180− if e.errno != errno.EEXIST:
181− raise
182−
183− with open(filepath, "wb") as out_file:
184− json.dump(schema, out_file, indent=4, sort_keys=True)
185− elif arguments.command == "serve":
186− try:
187− from flask import Flask, jsonify
188− except ImportError:
189− print(textwrap.dedent("""
190− The Flask library is required to serve the remote schemas.
191−
192− You can install it by running `pip install Flask`.
193−
194− Alternatively, see the `jsonschema_suite remotes` or
195− `jsonschema_suite dump_remotes` commands to create static files
196− that can be served with your own web server.
197− """.strip("\n")))
198− sys.exit(1)
199−
200− app = Flask(__name__)
201−
202− @app.route("/<path:path>")
203− def serve_path(path):
204− if path in REMOTES:
205− return jsonify(REMOTES[path])
206− return "Document does not exist.", 404
207−
208− app.run(port=1234)
209−
210−
211−parser = argparse.ArgumentParser(
212− description="JSON Schema Test Suite utilities",
213−)
214−subparsers = parser.add_subparsers(help="utility commands", dest="command")
215−
216−check = subparsers.add_parser("check", help="Sanity check the test suite.")
217−
218−flatten = subparsers.add_parser(
219− "flatten",
220− help="Output a flattened file containing a selected version's test cases."
221−)
222−flatten.add_argument(
223− "--randomize",
224− action="store_true",
225− help="Randomize the order of the outputted cases.",
226−)
227−flatten.add_argument(
228− "version", help="The directory containing the version to output",
229−)
230−
231−remotes = subparsers.add_parser(
232− "remotes",
233− help="Output the expected URLs and their associated schemas for remote "
234− "ref tests as a JSON object."
235−)
236−
237−dump_remotes = subparsers.add_parser(
238− "dump_remotes", help="Dump the remote ref schemas into a file tree",
239−)
240−dump_remotes.add_argument(
241− "--update",
242− action="store_true",
243− help="Update the remotes in an existing directory.",
244−)
245−dump_remotes.add_argument(
246− "--out-dir",
247− default=REMOTES_DIR,
248− type=os.path.abspath,
249− help="The output directory to create as the root of the file tree",
250−)
251−
252−serve = subparsers.add_parser(
253− "serve",
254− help="Start a webserver to serve schemas used by remote ref tests."
255−)
256−
257−if __name__ == "__main__":
258− main(parser.parse_args())
JSON-Schema-Test-Suite/index.jsdeleted−32
@@ -1,32 +0,0 @@
1−'use strict';
2−
3−var Ajv = require('ajv');
4−var jsonSchemaTest = require('json-schema-test');
5−var assert = require('assert');
6−
7−var refs = {
8− 'http://localhost:1234/integer.json': require('./remotes/integer.json'),
9− 'http://localhost:1234/subSchemas.json': require('./remotes/subSchemas.json'),
10− 'http://localhost:1234/folder/folderInteger.json': require('./remotes/folder/folderInteger.json'),
11− 'http://localhost:1234/name.json': require('./remotes/name.json')
12−};
13−
14−runTest(4);
15−runTest(6);
16−
17−function runTest(draft) {
18− var opts = {};
19− if (draft == 4) opts.meta = false;
20− var ajv = new Ajv(opts);
21− ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json'));
22− if (draft == 4) ajv._opts.defaultMeta = 'http://json-schema.org/draft-04/schema#';
23− for (var uri in refs) ajv.addSchema(refs[uri], uri);
24−
25− jsonSchemaTest(ajv, {
26− description: 'Test suite draft-0' + draft,
27− suites: {tests: './tests/draft' + draft + '/{**/,}*.json'},
28− skip: draft == 4 ? ['optional/zeroTerminatedFloats'] : [],
29− cwd: __dirname,
30− hideFolder: 'tests/'
31− });
32−}
JSON-Schema-Test-Suite/package.jsondeleted−28
@@ -1,28 +0,0 @@
1−{
2− "name": "json-schema-test-suite",
3− "version": "0.1.0",
4− "description": "A language agnostic test suite for the JSON Schema specifications",
5− "main": "index.js",
6− "scripts": {
7− "test": "mocha index.js -R spec"
8− },
9− "repository": {
10− "type": "git",
11− "url": "git+https://github.com/json-schema-org/JSON-Schema-Test-Suite.git"
12− },
13− "keywords": [
14− "json-schema",
15− "tests"
16− ],
17− "author": "http://json-schema.org",
18− "license": "MIT",
19− "bugs": {
20− "url": "https://github.com/json-schema-org/JSON-Schema-Test-Suite/issues"
21− },
22− "homepage": "https://github.com/json-schema-org/JSON-Schema-Test-Suite#readme",
23− "devDependencies": {
24− "ajv": "^5.0.4-beta.0",
25− "json-schema-test": "^1.3.0",
26− "mocha": "^3.2.0"
27− }
28−}
JSON-Schema-Test-Suite/remotes/folder/folderInteger.jsondeleted−3
@@ -1,3 +0,0 @@
1−{
2− "type": "integer"
3−}
JSON-Schema-Test-Suite/remotes/integer.jsondeleted−3
@@ -1,3 +0,0 @@
1−{
2− "type": "integer"
3−}
JSON-Schema-Test-Suite/remotes/name.jsondeleted−11
@@ -1,11 +0,0 @@
1−{
2− "definitions": {
3− "orNull": {
4− "anyOf": [
5− {"type": "null"},
6− {"$ref": "#"}
7− ]
8− }
9− },
10− "type": "string"
11−}
JSON-Schema-Test-Suite/remotes/subSchemas.jsondeleted−8
@@ -1,8 +0,0 @@
1−{
2− "integer": {
3− "type": "integer"
4− },
5− "refToInteger": {
6− "$ref": "#/integer"
7− }
8−}
JSON-Schema-Test-Suite/shell.nixdeleted−8
@@ -1,8 +0,0 @@
1−with import <nixpkgs> {};
2−
3−stdenv.mkDerivation {
4− name = "none";
5− buildInputs = [
6− pythonPackages.jsonschema
7− ];
8−}
JSON-Schema-Test-Suite/test-schema.jsondeleted−28
@@ -1,28 +0,0 @@
1−{
2− "$schema": "http://json-schema.org/draft-04/schema#",
3− "type": "array",
4− "items": {
5− "type": "object",
6− "required": ["description", "schema", "tests"],
7− "properties": {
8− "description": {"type": "string"},
9− "schema": {},
10− "tests": {
11− "type": "array",
12− "items": {
13− "type": "object",
14− "required": ["description", "data", "valid"],
15− "properties": {
16− "description": {"type": "string"},
17− "data": {},
18− "valid": {"type": "boolean"}
19− },
20− "additionalProperties": false
21− },
22− "minItems": 1
23− }
24− },
25− "additionalProperties": false,
26− "minItems": 1
27− }
28−}
JSON-Schema-Test-Suite/tests/draft3/additionalItems.jsondeleted−82
@@ -1,82 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft3/additionalProperties.jsondeleted−88
@@ -1,88 +0,0 @@
1−[
2− {
3− "description":
4− "additionalProperties being false does not allow other properties",
5− "schema": {
6− "properties": {"foo": {}, "bar": {}},
7− "patternProperties": { "^v": {} },
8− "additionalProperties": false
9− },
10− "tests": [
11− {
12− "description": "no additional properties is valid",
13− "data": {"foo": 1},
14− "valid": true
15− },
16− {
17− "description": "an additional property is invalid",
18− "data": {"foo" : 1, "bar" : 2, "quux" : "boom"},
19− "valid": false
20− },
21− {
22− "description": "ignores non-objects",
23− "data": [1, 2, 3],
24− "valid": true
25− },
26− {
27− "description": "patternProperties are not additional properties",
28− "data": {"foo":1, "vroom": 2},
29− "valid": true
30− }
31− ]
32− },
33− {
34− "description":
35− "additionalProperties allows a schema which should validate",
36− "schema": {
37− "properties": {"foo": {}, "bar": {}},
38− "additionalProperties": {"type": "boolean"}
39− },
40− "tests": [
41− {
42− "description": "no additional properties is valid",
43− "data": {"foo": 1},
44− "valid": true
45− },
46− {
47− "description": "an additional valid property is valid",
48− "data": {"foo" : 1, "bar" : 2, "quux" : true},
49− "valid": true
50− },
51− {
52− "description": "an additional invalid property is invalid",
53− "data": {"foo" : 1, "bar" : 2, "quux" : 12},
54− "valid": false
55− }
56− ]
57− },
58− {
59− "description":
60− "additionalProperties can exist by itself",
61− "schema": {
62− "additionalProperties": {"type": "boolean"}
63− },
64− "tests": [
65− {
66− "description": "an additional valid property is valid",
67− "data": {"foo" : true},
68− "valid": true
69− },
70− {
71− "description": "an additional invalid property is invalid",
72− "data": {"foo" : 1},
73− "valid": false
74− }
75− ]
76− },
77− {
78− "description": "additionalProperties are allowed by default",
79− "schema": {"properties": {"foo": {}, "bar": {}}},
80− "tests": [
81− {
82− "description": "additional properties are allowed",
83− "data": {"foo": 1, "bar": 2, "quux": true},
84− "valid": true
85− }
86− ]
87− }
88−]
JSON-Schema-Test-Suite/tests/draft3/default.jsondeleted−49
@@ -1,49 +0,0 @@
1−[
2− {
3− "description": "invalid type for default",
4− "schema": {
5− "properties": {
6− "foo": {
7− "type": "integer",
8− "default": []
9− }
10− }
11− },
12− "tests": [
13− {
14− "description": "valid when property is specified",
15− "data": {"foo": 13},
16− "valid": true
17− },
18− {
19− "description": "still valid when the invalid default is used",
20− "data": {},
21− "valid": true
22− }
23− ]
24− },
25− {
26− "description": "invalid string value for default",
27− "schema": {
28− "properties": {
29− "bar": {
30− "type": "string",
31− "minLength": 4,
32− "default": "bad"
33− }
34− }
35− },
36− "tests": [
37− {
38− "description": "valid when property is specified",
39− "data": {"bar": "good"},
40− "valid": true
41− },
42− {
43− "description": "still valid when the invalid default is used",
44− "data": {},
45− "valid": true
46− }
47− ]
48− }
49−]
JSON-Schema-Test-Suite/tests/draft3/dependencies.jsondeleted−108
@@ -1,108 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft3/disallow.jsondeleted−80
@@ -1,80 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft3/divisibleBy.jsondeleted−60
@@ -1,60 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft3/enum.jsondeleted−71
@@ -1,71 +0,0 @@
1−[
2− {
3− "description": "simple enum validation",
4− "schema": {"enum": [1, 2, 3]},
5− "tests": [
6− {
7− "description": "one of the enum is valid",
8− "data": 1,
9− "valid": true
10− },
11− {
12− "description": "something else is invalid",
13− "data": 4,
14− "valid": false
15− }
16− ]
17− },
18− {
19− "description": "heterogeneous enum validation",
20− "schema": {"enum": [6, "foo", [], true, {"foo": 12}]},
21− "tests": [
22− {
23− "description": "one of the enum is valid",
24− "data": [],
25− "valid": true
26− },
27− {
28− "description": "something else is invalid",
29− "data": null,
30− "valid": false
31− },
32− {
33− "description": "objects are deep compared",
34− "data": {"foo": false},
35− "valid": false
36− }
37− ]
38− },
39− {
40− "description": "enums in properties",
41− "schema": {
42− "type":"object",
43− "properties": {
44− "foo": {"enum":["foo"]},
45− "bar": {"enum":["bar"], "required":true}
46− }
47− },
48− "tests": [
49− {
50− "description": "both properties are valid",
51− "data": {"foo":"foo", "bar":"bar"},
52− "valid": true
53− },
54− {
55− "description": "missing optional property is valid",
56− "data": {"bar":"bar"},
57− "valid": true
58− },
59− {
60− "description": "missing required property is invalid",
61− "data": {"foo":"foo"},
62− "valid": false
63− },
64− {
65− "description": "missing all properties is invalid",
66− "data": {},
67− "valid": false
68− }
69− ]
70− }
71−]
JSON-Schema-Test-Suite/tests/draft3/extends.jsondeleted−94
@@ -1,94 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft3/items.jsondeleted−46
@@ -1,46 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft3/maxItems.jsondeleted−28
@@ -1,28 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft3/maxLength.jsondeleted−33
@@ -1,33 +0,0 @@
1−[
2− {
3− "description": "maxLength validation",
4− "schema": {"maxLength": 2},
5− "tests": [
6− {
7− "description": "shorter is valid",
8− "data": "f",
9− "valid": true
10− },
11− {
12− "description": "exact length is valid",
13− "data": "fo",
14− "valid": true
15− },
16− {
17− "description": "too long is invalid",
18− "data": "foo",
19− "valid": false
20− },
21− {
22− "description": "ignores non-strings",
23− "data": 10,
24− "valid": true
25− },
26− {
27− "description": "two supplementary Unicode code points is long enough",
28− "data": "\uD83D\uDCA9\uD83D\uDCA9",
29− "valid": true
30− }
31− ]
32− }
33−]
JSON-Schema-Test-Suite/tests/draft3/maximum.jsondeleted−42
@@ -1,42 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft3/minItems.jsondeleted−28
@@ -1,28 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft3/minLength.jsondeleted−33
@@ -1,33 +0,0 @@
1−[
2− {
3− "description": "minLength validation",
4− "schema": {"minLength": 2},
5− "tests": [
6− {
7− "description": "longer is valid",
8− "data": "foo",
9− "valid": true
10− },
11− {
12− "description": "exact length is valid",
13− "data": "fo",
14− "valid": true
15− },
16− {
17− "description": "too short is invalid",
18− "data": "f",
19− "valid": false
20− },
21− {
22− "description": "ignores non-strings",
23− "data": 1,
24− "valid": true
25− },
26− {
27− "description": "one supplementary Unicode code point is not long enough",
28− "data": "\uD83D\uDCA9",
29− "valid": false
30− }
31− ]
32− }
33−]
JSON-Schema-Test-Suite/tests/draft3/minimum.jsondeleted−42
@@ -1,42 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft3/optional/bignum.jsondeleted−107
@@ -1,107 +0,0 @@
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": "integer",
26− "schema": {"type": "integer"},
27− "tests": [
28− {
29− "description": "a negative bignum is an integer",
30− "data": -12345678910111213141516171819202122232425262728293031,
31− "valid": true
32− }
33− ]
34− },
35− {
36− "description": "number",
37− "schema": {"type": "number"},
38− "tests": [
39− {
40− "description": "a negative bignum is a number",
41− "data": -98249283749234923498293171823948729348710298301928331,
42− "valid": true
43− }
44− ]
45− },
46− {
47− "description": "string",
48− "schema": {"type": "string"},
49− "tests": [
50− {
51− "description": "a bignum is not a string",
52− "data": 98249283749234923498293171823948729348710298301928331,
53− "valid": false
54− }
55− ]
56− },
57− {
58− "description": "integer comparison",
59− "schema": {"maximum": 18446744073709551615},
60− "tests": [
61− {
62− "description": "comparison works for high numbers",
63− "data": 18446744073709551600,
64− "valid": true
65− }
66− ]
67− },
68− {
69− "description": "float comparison with high precision",
70− "schema": {
71− "maximum": 972783798187987123879878123.18878137,
72− "exclusiveMaximum": true
73− },
74− "tests": [
75− {
76− "description": "comparison works for high numbers",
77− "data": 972783798187987123879878123.188781371,
78− "valid": false
79− }
80− ]
81− },
82− {
83− "description": "integer comparison",
84− "schema": {"minimum": -18446744073709551615},
85− "tests": [
86− {
87− "description": "comparison works for very negative numbers",
88− "data": -18446744073709551600,
89− "valid": true
90− }
91− ]
92− },
93− {
94− "description": "float comparison with high precision on negative numbers",
95− "schema": {
96− "minimum": -972783798187987123879878123.18878137,
97− "exclusiveMinimum": true
98− },
99− "tests": [
100− {
101− "description": "comparison works for very negative numbers",
102− "data": -972783798187987123879878123.188781371,
103− "valid": false
104− }
105− ]
106− }
107−]
JSON-Schema-Test-Suite/tests/draft3/optional/format.jsondeleted−222
@@ -1,222 +0,0 @@
1−[
2− {
3− "description": "validation of regular expressions",
4− "schema": {"format": "regex"},
5− "tests": [
6− {
7− "description": "a valid regular expression",
8− "data": "([abc])+\\s+$",
9− "valid": true
10− },
11− {
12− "description": "a regular expression with unclosed parens is invalid",
13− "data": "^(abc]",
14− "valid": false
15− }
16− ]
17− },
18− {
19− "description": "validation of date-time strings",
20− "schema": {"format": "date-time"},
21− "tests": [
22− {
23− "description": "a valid date-time string",
24− "data": "1963-06-19T08:30:06.283185Z",
25− "valid": true
26− },
27− {
28− "description": "an invalid date-time string",
29− "data": "06/19/1963 08:30:06 PST",
30− "valid": false
31− },
32− {
33− "description": "only RFC3339 not all of ISO 8601 are valid",
34− "data": "2013-350T01:01:01",
35− "valid": false
36− }
37− ]
38− },
39− {
40− "description": "validation of date strings",
41− "schema": {"format": "date"},
42− "tests": [
43− {
44− "description": "a valid date string",
45− "data": "1963-06-19",
46− "valid": true
47− },
48− {
49− "description": "an invalid date string",
50− "data": "06/19/1963",
51− "valid": false
52− }
53− ]
54− },
55− {
56− "description": "validation of time strings",
57− "schema": {"format": "time"},
58− "tests": [
59− {
60− "description": "a valid time string",
61− "data": "08:30:06",
62− "valid": true
63− },
64− {
65− "description": "an invalid time string",
66− "data": "8:30 AM",
67− "valid": false
68− }
69− ]
70− },
71− {
72− "description": "validation of URIs",
73− "schema": {"format": "uri"},
74− "tests": [
75− {
76− "description": "a valid URI",
77− "data": "http://foo.bar/?baz=qux#quux",
78− "valid": true
79− },
80− {
81− "description": "an invalid protocol-relative URI Reference",
82− "data": "//foo.bar/?baz=qux#quux",
83− "valid": false
84− },
85− {
86− "description": "an invalid URI",
87− "data": "\\\\WINDOWS\\fileshare",
88− "valid": false
89− },
90− {
91− "description": "an invalid URI though valid URI reference",
92− "data": "abc",
93− "valid": false
94− }
95− ]
96− },
97− {
98− "description": "validation of e-mail addresses",
99− "schema": {"format": "email"},
100− "tests": [
101− {
102− "description": "a valid e-mail address",
103− "data": "joe.bloggs@example.com",
104− "valid": true
105− },
106− {
107− "description": "an invalid e-mail address",
108− "data": "2962",
109− "valid": false
110− }
111− ]
112− },
113− {
114− "description": "validation of IP addresses",
115− "schema": {"format": "ip-address"},
116− "tests": [
117− {
118− "description": "a valid IP address",
119− "data": "192.168.0.1",
120− "valid": true
121− },
122− {
123− "description": "an IP address with too many components",
124− "data": "127.0.0.0.1",
125− "valid": false
126− },
127− {
128− "description": "an IP address with out-of-range values",
129− "data": "256.256.256.256",
130− "valid": false
131− }
132− ]
133− },
134− {
135− "description": "validation of IPv6 addresses",
136− "schema": {"format": "ipv6"},
137− "tests": [
138− {
139− "description": "a valid IPv6 address",
140− "data": "::1",
141− "valid": true
142− },
143− {
144− "description": "an IPv6 address with out-of-range values",
145− "data": "12345::",
146− "valid": false
147− },
148− {
149− "description": "an IPv6 address with too many components",
150− "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1",
151− "valid": false
152− },
153− {
154− "description": "an IPv6 address containing illegal characters",
155− "data": "::laptop",
156− "valid": false
157− }
158− ]
159− },
160− {
161− "description": "validation of host names",
162− "schema": {"format": "host-name"},
163− "tests": [
164− {
165− "description": "a valid host name",
166− "data": "www.example.com",
167− "valid": true
168− },
169− {
170− "description": "a host name starting with an illegal character",
171− "data": "-a-host-name-that-starts-with--",
172− "valid": false
173− },
174− {
175− "description": "a host name containing illegal characters",
176− "data": "not_a_valid_host_name",
177− "valid": false
178− },
179− {
180− "description": "a host name with a component too long",
181− "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component",
182− "valid": false
183− }
184− ]
185− },
186− {
187− "description": "validation of CSS colors",
188− "schema": {"format": "color"},
189− "tests": [
190− {
191− "description": "a valid CSS color name",
192− "data": "fuchsia",
193− "valid": true
194− },
195− {
196− "description": "a valid six-digit CSS color code",
197− "data": "#CC8899",
198− "valid": true
199− },
200− {
201− "description": "a valid three-digit CSS color code",
202− "data": "#C89",
203− "valid": true
204− },
205− {
206− "description": "an invalid CSS color code",
207− "data": "#00332520",
208− "valid": false
209− },
210− {
211− "description": "an invalid CSS color name",
212− "data": "puce",
213− "valid": false
214− },
215− {
216− "description": "a CSS color name containing invalid characters",
217− "data": "light_grayish_red-violet",
218− "valid": false
219− }
220− ]
221− }
222−]
JSON-Schema-Test-Suite/tests/draft3/optional/jsregex.jsondeleted−18
@@ -1,18 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft3/optional/zeroTerminatedFloats.jsondeleted−15
@@ -1,15 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft3/pattern.jsondeleted−34
@@ -1,34 +0,0 @@
1−[
2− {
3− "description": "pattern validation",
4− "schema": {"pattern": "^a*$"},
5− "tests": [
6− {
7− "description": "a matching pattern is valid",
8− "data": "aaa",
9− "valid": true
10− },
11− {
12− "description": "a non-matching pattern is invalid",
13− "data": "abc",
14− "valid": false
15− },
16− {
17− "description": "ignores non-strings",
18− "data": true,
19− "valid": true
20− }
21− ]
22− },
23− {
24− "description": "pattern is not anchored",
25− "schema": {"pattern": "a+"},
26− "tests": [
27− {
28− "description": "matches a substring",
29− "data": "xxaayy",
30− "valid": true
31− }
32− ]
33− }
34−]
JSON-Schema-Test-Suite/tests/draft3/patternProperties.jsondeleted−110
@@ -1,110 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft3/properties.jsondeleted−92
@@ -1,92 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft3/ref.jsondeleted−192
@@ -1,192 +0,0 @@
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 invalid",
90− "data": {"slash": "aoeu"},
91− "valid": false
92− },
93− {
94− "description": "tilda invalid",
95− "data": {"tilda": "aoeu"},
96− "valid": false
97− },
98− {
99− "description": "percent invalid",
100− "data": {"percent": "aoeu"},
101− "valid": false
102− },
103− {
104− "description": "slash valid",
105− "data": {"slash": 123},
106− "valid": true
107− },
108− {
109− "description": "tilda valid",
110− "data": {"tilda": 123},
111− "valid": true
112− },
113− {
114− "description": "percent valid",
115− "data": {"percent": 123},
116− "valid": true
117− }
118− ]
119− },
120− {
121− "description": "nested refs",
122− "schema": {
123− "definitions": {
124− "a": {"type": "integer"},
125− "b": {"$ref": "#/definitions/a"},
126− "c": {"$ref": "#/definitions/b"}
127− },
128− "$ref": "#/definitions/c"
129− },
130− "tests": [
131− {
132− "description": "nested ref valid",
133− "data": 5,
134− "valid": true
135− },
136− {
137− "description": "nested ref invalid",
138− "data": "a",
139− "valid": false
140− }
141− ]
142− },
143− {
144− "description": "ref overrides any sibling keywords",
145− "schema": {
146− "definitions": {
147− "reffed": {
148− "type": "array"
149− }
150− },
151− "properties": {
152− "foo": {
153− "$ref": "#/definitions/reffed",
154− "maxItems": 2
155− }
156− }
157− },
158− "tests": [
159− {
160− "description": "remote ref valid",
161− "data": { "foo": [] },
162− "valid": true
163− },
164− {
165− "description": "remote ref valid, maxItems ignored",
166− "data": { "foo": [ 1, 2, 3] },
167− "valid": true
168− },
169− {
170− "description": "ref invalid",
171− "data": { "foo": "string" },
172− "valid": false
173− }
174− ]
175− },
176− {
177− "description": "remote ref, containing refs itself",
178− "schema": {"$ref": "http://json-schema.org/draft-03/schema#"},
179− "tests": [
180− {
181− "description": "remote ref valid",
182− "data": {"items": {"type": "integer"}},
183− "valid": true
184− },
185− {
186− "description": "remote ref invalid",
187− "data": {"items": {"type": 1}},
188− "valid": false
189− }
190− ]
191− }
192−]
JSON-Schema-Test-Suite/tests/draft3/refRemote.jsondeleted−74
@@ -1,74 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft3/required.jsondeleted−53
@@ -1,53 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft3/type.jsondeleted−489
@@ -1,489 +0,0 @@
1−[
2− {
3− "description": "integer type matches integers",
4− "schema": {"type": "integer"},
5− "tests": [
6− {
7− "description": "an integer is an integer",
8− "data": 1,
9− "valid": true
10− },
11− {
12− "description": "a float is not an integer",
13− "data": 1.1,
14− "valid": false
15− },
16− {
17− "description": "a string is not an integer",
18− "data": "foo",
19− "valid": false
20− },
21− {
22− "description": "a string is still not an integer, even if it looks like one",
23− "data": "1",
24− "valid": false
25− },
26− {
27− "description": "an object is not an integer",
28− "data": {},
29− "valid": false
30− },
31− {
32− "description": "an array is not an integer",
33− "data": [],
34− "valid": false
35− },
36− {
37− "description": "a boolean is not an integer",
38− "data": true,
39− "valid": false
40− },
41− {
42− "description": "null is not an integer",
43− "data": null,
44− "valid": false
45− }
46− ]
47− },
48− {
49− "description": "number type matches numbers",
50− "schema": {"type": "number"},
51− "tests": [
52− {
53− "description": "an integer is a number",
54− "data": 1,
55− "valid": true
56− },
57− {
58− "description": "a float is a number",
59− "data": 1.1,
60− "valid": true
61− },
62− {
63− "description": "a string is not a number",
64− "data": "foo",
65− "valid": false
66− },
67− {
68− "description": "a string is still not a number, even if it looks like one",
69− "data": "1",
70− "valid": false
71− },
72− {
73− "description": "an object is not a number",
74− "data": {},
75− "valid": false
76− },
77− {
78− "description": "an array is not a number",
79− "data": [],
80− "valid": false
81− },
82− {
83− "description": "a boolean is not a number",
84− "data": true,
85− "valid": false
86− },
87− {
88− "description": "null is not a number",
89− "data": null,
90− "valid": false
91− }
92− ]
93− },
94− {
95− "description": "string type matches strings",
96− "schema": {"type": "string"},
97− "tests": [
98− {
99− "description": "1 is not a string",
100− "data": 1,
101− "valid": false
102− },
103− {
104− "description": "a float is not a string",
105− "data": 1.1,
106− "valid": false
107− },
108− {
109− "description": "a string is a string",
110− "data": "foo",
111− "valid": true
112− },
113− {
114− "description": "a string is still a string, even if it looks like a number",
115− "data": "1",
116− "valid": true
117− },
118− {
119− "description": "an object is not a string",
120− "data": {},
121− "valid": false
122− },
123− {
124− "description": "an array is not a string",
125− "data": [],
126− "valid": false
127− },
128− {
129− "description": "a boolean is not a string",
130− "data": true,
131− "valid": false
132− },
133− {
134− "description": "null is not a string",
135− "data": null,
136− "valid": false
137− }
138− ]
139− },
140− {
141− "description": "object type matches objects",
142− "schema": {"type": "object"},
143− "tests": [
144− {
145− "description": "an integer is not an object",
146− "data": 1,
147− "valid": false
148− },
149− {
150− "description": "a float is not an object",
151− "data": 1.1,
152− "valid": false
153− },
154− {
155− "description": "a string is not an object",
156− "data": "foo",
157− "valid": false
158− },
159− {
160− "description": "an object is an object",
161− "data": {},
162− "valid": true
163− },
164− {
165− "description": "an array is not an object",
166− "data": [],
167− "valid": false
168− },
169− {
170− "description": "a boolean is not an object",
171− "data": true,
172− "valid": false
173− },
174− {
175− "description": "null is not an object",
176− "data": null,
177− "valid": false
178− }
179− ]
180− },
181− {
182− "description": "array type matches arrays",
183− "schema": {"type": "array"},
184− "tests": [
185− {
186− "description": "an integer is not an array",
187− "data": 1,
188− "valid": false
189− },
190− {
191− "description": "a float is not an array",
192− "data": 1.1,
193− "valid": false
194− },
195− {
196− "description": "a string is not an array",
197− "data": "foo",
198− "valid": false
199− },
200− {
201− "description": "an object is not an array",
202− "data": {},
203− "valid": false
204− },
205− {
206− "description": "an array is an array",
207− "data": [],
208− "valid": true
209− },
210− {
211− "description": "a boolean is not an array",
212− "data": true,
213− "valid": false
214− },
215− {
216− "description": "null is not an array",
217− "data": null,
218− "valid": false
219− }
220− ]
221− },
222− {
223− "description": "boolean type matches booleans",
224− "schema": {"type": "boolean"},
225− "tests": [
226− {
227− "description": "an integer is not a boolean",
228− "data": 1,
229− "valid": false
230− },
231− {
232− "description": "a float is not a boolean",
233− "data": 1.1,
234− "valid": false
235− },
236− {
237− "description": "a string is not a boolean",
238− "data": "foo",
239− "valid": false
240− },
241− {
242− "description": "an object is not a boolean",
243− "data": {},
244− "valid": false
245− },
246− {
247− "description": "an array is not a boolean",
248− "data": [],
249− "valid": false
250− },
251− {
252− "description": "a boolean is a boolean",
253− "data": true,
254− "valid": true
255− },
256− {
257− "description": "null is not a boolean",
258− "data": null,
259− "valid": false
260− }
261− ]
262− },
263− {
264− "description": "null type matches only the null object",
265− "schema": {"type": "null"},
266− "tests": [
267− {
268− "description": "an integer is not null",
269− "data": 1,
270− "valid": false
271− },
272− {
273− "description": "a float is not null",
274− "data": 1.1,
275− "valid": false
276− },
277− {
278− "description": "a string is not null",
279− "data": "foo",
280− "valid": false
281− },
282− {
283− "description": "an object is not null",
284− "data": {},
285− "valid": false
286− },
287− {
288− "description": "an array is not null",
289− "data": [],
290− "valid": false
291− },
292− {
293− "description": "a boolean is not null",
294− "data": true,
295− "valid": false
296− },
297− {
298− "description": "null is null",
299− "data": null,
300− "valid": true
301− }
302− ]
303− },
304− {
305− "description": "any type matches any type",
306− "schema": {"type": "any"},
307− "tests": [
308− {
309− "description": "any type includes integers",
310− "data": 1,
311− "valid": true
312− },
313− {
314− "description": "any type includes float",
315− "data": 1.1,
316− "valid": true
317− },
318− {
319− "description": "any type includes string",
320− "data": "foo",
321− "valid": true
322− },
323− {
324− "description": "any type includes object",
325− "data": {},
326− "valid": true
327− },
328− {
329− "description": "any type includes array",
330− "data": [],
331− "valid": true
332− },
333− {
334− "description": "any type includes boolean",
335− "data": true,
336− "valid": true
337− },
338− {
339− "description": "any type includes null",
340− "data": null,
341− "valid": true
342− }
343− ]
344− },
345− {
346− "description": "multiple types can be specified in an array",
347− "schema": {"type": ["integer", "string"]},
348− "tests": [
349− {
350− "description": "an integer is valid",
351− "data": 1,
352− "valid": true
353− },
354− {
355− "description": "a string is valid",
356− "data": "foo",
357− "valid": true
358− },
359− {
360− "description": "a float is invalid",
361− "data": 1.1,
362− "valid": false
363− },
364− {
365− "description": "an object is invalid",
366− "data": {},
367− "valid": false
368− },
369− {
370− "description": "an array is invalid",
371− "data": [],
372− "valid": false
373− },
374− {
375− "description": "a boolean is invalid",
376− "data": true,
377− "valid": false
378− },
379− {
380− "description": "null is invalid",
381− "data": null,
382− "valid": false
383− }
384− ]
385− },
386− {
387− "description": "types can include schemas",
388− "schema": {
389− "type": [
390− "array",
391− {"type": "object"}
392− ]
393− },
394− "tests": [
395− {
396− "description": "an integer is invalid",
397− "data": 1,
398− "valid": false
399− },
400− {
401− "description": "a string is invalid",
402− "data": "foo",
403− "valid": false
404− },
405− {
406− "description": "a float is invalid",
407− "data": 1.1,
408− "valid": false
409− },
410− {
411− "description": "an object is valid",
412− "data": {},
413− "valid": true
414− },
415− {
416− "description": "an array is valid",
417− "data": [],
418− "valid": true
419− },
420− {
421− "description": "a boolean is invalid",
422− "data": true,
423− "valid": false
424− },
425− {
426− "description": "null is invalid",
427− "data": null,
428− "valid": false
429− }
430− ]
431− },
432− {
433− "description":
434− "when types includes a schema it should fully validate the schema",
435− "schema": {
436− "type": [
437− "integer",
438− {
439− "properties": {
440− "foo": {"type": "null"}
441− }
442− }
443− ]
444− },
445− "tests": [
446− {
447− "description": "an integer is valid",
448− "data": 1,
449− "valid": true
450− },
451− {
452− "description": "an object is valid only if it is fully valid",
453− "data": {"foo": null},
454− "valid": true
455− },
456− {
457− "description": "an object is invalid otherwise",
458− "data": {"foo": "bar"},
459− "valid": false
460− }
461− ]
462− },
463− {
464− "description": "types from separate schemas are merged",
465− "schema": {
466− "type": [
467− {"type": ["string"]},
468− {"type": ["array", "null"]}
469− ]
470− },
471− "tests": [
472− {
473− "description": "an integer is invalid",
474− "data": 1,
475− "valid": false
476− },
477− {
478− "description": "a string is valid",
479− "data": "foo",
480− "valid": true
481− },
482− {
483− "description": "an array is valid",
484− "data": [1, 2, 3],
485− "valid": true
486− }
487− ]
488− }
489−]
JSON-Schema-Test-Suite/tests/draft3/uniqueItems.jsondeleted−79
@@ -1,79 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft4/additionalItems.jsondeleted−87
@@ -1,87 +0,0 @@
1−[
2− {
3− "description": "additionalItems as schema",
4− "schema": {
5− "items": [{}],
6− "additionalItems": {"type": "integer"}
7− },
8− "tests": [
9− {
10− "description": "additional items match schema",
11− "data": [ null, 2, 3, 4 ],
12− "valid": true
13− },
14− {
15− "description": "additional items do not match schema",
16− "data": [ null, 2, 3, "foo" ],
17− "valid": false
18− }
19− ]
20− },
21− {
22− "description": "items is schema, no additionalItems",
23− "schema": {
24− "items": {},
25− "additionalItems": false
26− },
27− "tests": [
28− {
29− "description": "all items match schema",
30− "data": [ 1, 2, 3, 4, 5 ],
31− "valid": true
32− }
33− ]
34− },
35− {
36− "description": "array of items with no additionalItems",
37− "schema": {
38− "items": [{}, {}, {}],
39− "additionalItems": false
40− },
41− "tests": [
42− {
43− "description": "fewer number of items present",
44− "data": [ 1, 2 ],
45− "valid": true
46− },
47− {
48− "description": "equal number of items present",
49− "data": [ 1, 2, 3 ],
50− "valid": true
51− },
52− {
53− "description": "additional items are not permitted",
54− "data": [ 1, 2, 3, 4 ],
55− "valid": false
56− }
57− ]
58− },
59− {
60− "description": "additionalItems as false without items",
61− "schema": {"additionalItems": false},
62− "tests": [
63− {
64− "description":
65− "items defaults to empty schema so everything is valid",
66− "data": [ 1, 2, 3, 4, 5 ],
67− "valid": true
68− },
69− {
70− "description": "ignores non-arrays",
71− "data": {"foo" : "bar"},
72− "valid": true
73− }
74− ]
75− },
76− {
77− "description": "additionalItems are allowed by default",
78− "schema": {"items": [{"type": "integer"}]},
79− "tests": [
80− {
81− "description": "only the first item is validated",
82− "data": [1, "foo", false],
83− "valid": true
84− }
85− ]
86− }
87−]
JSON-Schema-Test-Suite/tests/draft4/additionalProperties.jsondeleted−88
@@ -1,88 +0,0 @@
1−[
2− {
3− "description":
4− "additionalProperties being false does not allow other properties",
5− "schema": {
6− "properties": {"foo": {}, "bar": {}},
7− "patternProperties": { "^v": {} },
8− "additionalProperties": false
9− },
10− "tests": [
11− {
12− "description": "no additional properties is valid",
13− "data": {"foo": 1},
14− "valid": true
15− },
16− {
17− "description": "an additional property is invalid",
18− "data": {"foo" : 1, "bar" : 2, "quux" : "boom"},
19− "valid": false
20− },
21− {
22− "description": "ignores non-objects",
23− "data": [1, 2, 3],
24− "valid": true
25− },
26− {
27− "description": "patternProperties are not additional properties",
28− "data": {"foo":1, "vroom": 2},
29− "valid": true
30− }
31− ]
32− },
33− {
34− "description":
35− "additionalProperties allows a schema which should validate",
36− "schema": {
37− "properties": {"foo": {}, "bar": {}},
38− "additionalProperties": {"type": "boolean"}
39− },
40− "tests": [
41− {
42− "description": "no additional properties is valid",
43− "data": {"foo": 1},
44− "valid": true
45− },
46− {
47− "description": "an additional valid property is valid",
48− "data": {"foo" : 1, "bar" : 2, "quux" : true},
49− "valid": true
50− },
51− {
52− "description": "an additional invalid property is invalid",
53− "data": {"foo" : 1, "bar" : 2, "quux" : 12},
54− "valid": false
55− }
56− ]
57− },
58− {
59− "description":
60− "additionalProperties can exist by itself",
61− "schema": {
62− "additionalProperties": {"type": "boolean"}
63− },
64− "tests": [
65− {
66− "description": "an additional valid property is valid",
67− "data": {"foo" : true},
68− "valid": true
69− },
70− {
71− "description": "an additional invalid property is invalid",
72− "data": {"foo" : 1},
73− "valid": false
74− }
75− ]
76− },
77− {
78− "description": "additionalProperties are allowed by default",
79− "schema": {"properties": {"foo": {}, "bar": {}}},
80− "tests": [
81− {
82− "description": "additional properties are allowed",
83− "data": {"foo": 1, "bar": 2, "quux": true},
84− "valid": true
85− }
86− ]
87− }
88−]
JSON-Schema-Test-Suite/tests/draft4/allOf.jsondeleted−112
@@ -1,112 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft4/anyOf.jsondeleted−68
@@ -1,68 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft4/default.jsondeleted−49
@@ -1,49 +0,0 @@
1−[
2− {
3− "description": "invalid type for default",
4− "schema": {
5− "properties": {
6− "foo": {
7− "type": "integer",
8− "default": []
9− }
10− }
11− },
12− "tests": [
13− {
14− "description": "valid when property is specified",
15− "data": {"foo": 13},
16− "valid": true
17− },
18− {
19− "description": "still valid when the invalid default is used",
20− "data": {},
21− "valid": true
22− }
23− ]
24− },
25− {
26− "description": "invalid string value for default",
27− "schema": {
28− "properties": {
29− "bar": {
30− "type": "string",
31− "minLength": 4,
32− "default": "bad"
33− }
34− }
35− },
36− "tests": [
37− {
38− "description": "valid when property is specified",
39− "data": {"bar": "good"},
40− "valid": true
41− },
42− {
43− "description": "still valid when the invalid default is used",
44− "data": {},
45− "valid": true
46− }
47− ]
48− }
49−]
JSON-Schema-Test-Suite/tests/draft4/definitions.jsondeleted−32
@@ -1,32 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft4/dependencies.jsondeleted−113
@@ -1,113 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft4/enum.jsondeleted−72
@@ -1,72 +0,0 @@
1−[
2− {
3− "description": "simple enum validation",
4− "schema": {"enum": [1, 2, 3]},
5− "tests": [
6− {
7− "description": "one of the enum is valid",
8− "data": 1,
9− "valid": true
10− },
11− {
12− "description": "something else is invalid",
13− "data": 4,
14− "valid": false
15− }
16− ]
17− },
18− {
19− "description": "heterogeneous enum validation",
20− "schema": {"enum": [6, "foo", [], true, {"foo": 12}]},
21− "tests": [
22− {
23− "description": "one of the enum is valid",
24− "data": [],
25− "valid": true
26− },
27− {
28− "description": "something else is invalid",
29− "data": null,
30− "valid": false
31− },
32− {
33− "description": "objects are deep compared",
34− "data": {"foo": false},
35− "valid": false
36− }
37− ]
38− },
39− {
40− "description": "enums in properties",
41− "schema": {
42− "type":"object",
43− "properties": {
44− "foo": {"enum":["foo"]},
45− "bar": {"enum":["bar"]}
46− },
47− "required": ["bar"]
48− },
49− "tests": [
50− {
51− "description": "both properties are valid",
52− "data": {"foo":"foo", "bar":"bar"},
53− "valid": true
54− },
55− {
56− "description": "missing optional property is valid",
57− "data": {"bar":"bar"},
58− "valid": true
59− },
60− {
61− "description": "missing required property is invalid",
62− "data": {"foo":"foo"},
63− "valid": false
64− },
65− {
66− "description": "missing all properties is invalid",
67− "data": {},
68− "valid": false
69− }
70− ]
71− }
72−]
JSON-Schema-Test-Suite/tests/draft4/items.jsondeleted−78
@@ -1,78 +0,0 @@
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− "description": "JavaScript pseudo-array is valid",
25− "data": {
26− "0": "invalid",
27− "length": 1
28− },
29− "valid": true
30− }
31− ]
32− },
33− {
34− "description": "an array of schemas for items",
35− "schema": {
36− "items": [
37− {"type": "integer"},
38− {"type": "string"}
39− ]
40− },
41− "tests": [
42− {
43− "description": "correct types",
44− "data": [ 1, "foo" ],
45− "valid": true
46− },
47− {
48− "description": "wrong types",
49− "data": [ "foo", 1 ],
50− "valid": false
51− },
52− {
53− "description": "incomplete array of items",
54− "data": [ 1 ],
55− "valid": true
56− },
57− {
58− "description": "array with additional items",
59− "data": [ 1, "foo", true ],
60− "valid": true
61− },
62− {
63− "description": "empty array",
64− "data": [ ],
65− "valid": true
66− },
67− {
68− "description": "JavaScript pseudo-array is valid",
69− "data": {
70− "0": "invalid",
71− "1": "valid",
72− "length": 2
73− },
74− "valid": true
75− }
76− ]
77− }
78−]
JSON-Schema-Test-Suite/tests/draft4/maxItems.jsondeleted−28
@@ -1,28 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft4/maxLength.jsondeleted−33
@@ -1,33 +0,0 @@
1−[
2− {
3− "description": "maxLength validation",
4− "schema": {"maxLength": 2},
5− "tests": [
6− {
7− "description": "shorter is valid",
8− "data": "f",
9− "valid": true
10− },
11− {
12− "description": "exact length is valid",
13− "data": "fo",
14− "valid": true
15− },
16− {
17− "description": "too long is invalid",
18− "data": "foo",
19− "valid": false
20− },
21− {
22− "description": "ignores non-strings",
23− "data": 100,
24− "valid": true
25− },
26− {
27− "description": "two supplementary Unicode code points is long enough",
28− "data": "\uD83D\uDCA9\uD83D\uDCA9",
29− "valid": true
30− }
31− ]
32− }
33−]
JSON-Schema-Test-Suite/tests/draft4/maxProperties.jsondeleted−28
@@ -1,28 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft4/maximum.jsondeleted−47
@@ -1,47 +0,0 @@
1−[
2− {
3− "description": "maximum validation",
4− "schema": {"maximum": 3.0},
5− "tests": [
6− {
7− "description": "below the maximum is valid",
8− "data": 2.6,
9− "valid": true
10− },
11− {
12− "description": "boundary point is valid",
13− "data": 3.0,
14− "valid": true
15− },
16− {
17− "description": "above the maximum is invalid",
18− "data": 3.5,
19− "valid": false
20− },
21− {
22− "description": "ignores non-numbers",
23− "data": "x",
24− "valid": true
25− }
26− ]
27− },
28− {
29− "description": "exclusiveMaximum validation",
30− "schema": {
31− "maximum": 3.0,
32− "exclusiveMaximum": true
33− },
34− "tests": [
35− {
36− "description": "below the maximum is still valid",
37− "data": 2.2,
38− "valid": true
39− },
40− {
41− "description": "boundary point is invalid",
42− "data": 3.0,
43− "valid": false
44− }
45− ]
46− }
47−]
JSON-Schema-Test-Suite/tests/draft4/minItems.jsondeleted−28
@@ -1,28 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft4/minLength.jsondeleted−33
@@ -1,33 +0,0 @@
1−[
2− {
3− "description": "minLength validation",
4− "schema": {"minLength": 2},
5− "tests": [
6− {
7− "description": "longer is valid",
8− "data": "foo",
9− "valid": true
10− },
11− {
12− "description": "exact length is valid",
13− "data": "fo",
14− "valid": true
15− },
16− {
17− "description": "too short is invalid",
18− "data": "f",
19− "valid": false
20− },
21− {
22− "description": "ignores non-strings",
23− "data": 1,
24− "valid": true
25− },
26− {
27− "description": "one supplementary Unicode code point is not long enough",
28− "data": "\uD83D\uDCA9",
29− "valid": false
30− }
31− ]
32− }
33−]
JSON-Schema-Test-Suite/tests/draft4/minProperties.jsondeleted−28
@@ -1,28 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft4/minimum.jsondeleted−47
@@ -1,47 +0,0 @@
1−[
2− {
3− "description": "minimum validation",
4− "schema": {"minimum": 1.1},
5− "tests": [
6− {
7− "description": "above the minimum is valid",
8− "data": 2.6,
9− "valid": true
10− },
11− {
12− "description": "boundary point is valid",
13− "data": 1.1,
14− "valid": true
15− },
16− {
17− "description": "below the minimum is invalid",
18− "data": 0.6,
19− "valid": false
20− },
21− {
22− "description": "ignores non-numbers",
23− "data": "x",
24− "valid": true
25− }
26− ]
27− },
28− {
29− "description": "exclusiveMinimum validation",
30− "schema": {
31− "minimum": 1.1,
32− "exclusiveMinimum": true
33− },
34− "tests": [
35− {
36− "description": "above the minimum is still valid",
37− "data": 1.2,
38− "valid": true
39− },
40− {
41− "description": "boundary point is invalid",
42− "data": 1.1,
43− "valid": false
44− }
45− ]
46− }
47−]
JSON-Schema-Test-Suite/tests/draft4/multipleOf.jsondeleted−60
@@ -1,60 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft4/not.jsondeleted−96
@@ -1,96 +0,0 @@
1−[
2− {
3− "description": "not",
4− "schema": {
5− "not": {"type": "integer"}
6− },
7− "tests": [
8− {
9− "description": "allowed",
10− "data": "foo",
11− "valid": true
12− },
13− {
14− "description": "disallowed",
15− "data": 1,
16− "valid": false
17− }
18− ]
19− },
20− {
21− "description": "not multiple types",
22− "schema": {
23− "not": {"type": ["integer", "boolean"]}
24− },
25− "tests": [
26− {
27− "description": "valid",
28− "data": "foo",
29− "valid": true
30− },
31− {
32− "description": "mismatch",
33− "data": 1,
34− "valid": false
35− },
36− {
37− "description": "other mismatch",
38− "data": true,
39− "valid": false
40− }
41− ]
42− },
43− {
44− "description": "not more complex schema",
45− "schema": {
46− "not": {
47− "type": "object",
48− "properties": {
49− "foo": {
50− "type": "string"
51− }
52− }
53− }
54− },
55− "tests": [
56− {
57− "description": "match",
58− "data": 1,
59− "valid": true
60− },
61− {
62− "description": "other match",
63− "data": {"foo": 1},
64− "valid": true
65− },
66− {
67− "description": "mismatch",
68− "data": {"foo": "bar"},
69− "valid": false
70− }
71− ]
72− },
73− {
74− "description": "forbidden property",
75− "schema": {
76− "properties": {
77− "foo": {
78− "not": {}
79− }
80− }
81− },
82− "tests": [
83− {
84− "description": "property present",
85− "data": {"foo": 1, "bar": 2},
86− "valid": false
87− },
88− {
89− "description": "property absent",
90− "data": {"bar": 1, "baz": 2},
91− "valid": true
92− }
93− ]
94− }
95−
96−]
JSON-Schema-Test-Suite/tests/draft4/oneOf.jsondeleted−68
@@ -1,68 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft4/optional/bignum.jsondeleted−107
@@ -1,107 +0,0 @@
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": "integer",
26− "schema": {"type": "integer"},
27− "tests": [
28− {
29− "description": "a negative bignum is an integer",
30− "data": -12345678910111213141516171819202122232425262728293031,
31− "valid": true
32− }
33− ]
34− },
35− {
36− "description": "number",
37− "schema": {"type": "number"},
38− "tests": [
39− {
40− "description": "a negative bignum is a number",
41− "data": -98249283749234923498293171823948729348710298301928331,
42− "valid": true
43− }
44− ]
45− },
46− {
47− "description": "string",
48− "schema": {"type": "string"},
49− "tests": [
50− {
51− "description": "a bignum is not a string",
52− "data": 98249283749234923498293171823948729348710298301928331,
53− "valid": false
54− }
55− ]
56− },
57− {
58− "description": "integer comparison",
59− "schema": {"maximum": 18446744073709551615},
60− "tests": [
61− {
62− "description": "comparison works for high numbers",
63− "data": 18446744073709551600,
64− "valid": true
65− }
66− ]
67− },
68− {
69− "description": "float comparison with high precision",
70− "schema": {
71− "maximum": 972783798187987123879878123.18878137,
72− "exclusiveMaximum": true
73− },
74− "tests": [
75− {
76− "description": "comparison works for high numbers",
77− "data": 972783798187987123879878123.188781371,
78− "valid": false
79− }
80− ]
81− },
82− {
83− "description": "integer comparison",
84− "schema": {"minimum": -18446744073709551615},
85− "tests": [
86− {
87− "description": "comparison works for very negative numbers",
88− "data": -18446744073709551600,
89− "valid": true
90− }
91− ]
92− },
93− {
94− "description": "float comparison with high precision on negative numbers",
95− "schema": {
96− "minimum": -972783798187987123879878123.18878137,
97− "exclusiveMinimum": true
98− },
99− "tests": [
100− {
101− "description": "comparison works for very negative numbers",
102− "data": -972783798187987123879878123.188781371,
103− "valid": false
104− }
105− ]
106− }
107−]
JSON-Schema-Test-Suite/tests/draft4/optional/ecmascript-regex.jsondeleted−13
@@ -1,13 +0,0 @@
1−[
2− {
3− "description": "ECMA 262 regex non-compliance",
4− "schema": { "format": "regex" },
5− "tests": [
6− {
7− "description": "ECMA 262 has no support for \\Z anchor from .NET",
8− "data": "^\\S(|(.|\\n)*\\S)\\Z",
9− "valid": false
10− }
11− ]
12− }
13−]
JSON-Schema-Test-Suite/tests/draft4/optional/format.jsondeleted−148
@@ -1,148 +0,0 @@
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 invalid protocol-relative URI Reference",
34− "data": "//foo.bar/?baz=qux#quux",
35− "valid": false
36− },
37− {
38− "description": "an invalid URI",
39− "data": "\\\\WINDOWS\\fileshare",
40− "valid": false
41− },
42− {
43− "description": "an invalid URI though valid URI reference",
44− "data": "abc",
45− "valid": false
46− }
47− ]
48− },
49− {
50− "description": "validation of e-mail addresses",
51− "schema": {"format": "email"},
52− "tests": [
53− {
54− "description": "a valid e-mail address",
55− "data": "joe.bloggs@example.com",
56− "valid": true
57− },
58− {
59− "description": "an invalid e-mail address",
60− "data": "2962",
61− "valid": false
62− }
63− ]
64− },
65− {
66− "description": "validation of IP addresses",
67− "schema": {"format": "ipv4"},
68− "tests": [
69− {
70− "description": "a valid IP address",
71− "data": "192.168.0.1",
72− "valid": true
73− },
74− {
75− "description": "an IP address with too many components",
76− "data": "127.0.0.0.1",
77− "valid": false
78− },
79− {
80− "description": "an IP address with out-of-range values",
81− "data": "256.256.256.256",
82− "valid": false
83− },
84− {
85− "description": "an IP address without 4 components",
86− "data": "127.0",
87− "valid": false
88− },
89− {
90− "description": "an IP address as an integer",
91− "data": "0x7f000001",
92− "valid": false
93− }
94− ]
95− },
96− {
97− "description": "validation of IPv6 addresses",
98− "schema": {"format": "ipv6"},
99− "tests": [
100− {
101− "description": "a valid IPv6 address",
102− "data": "::1",
103− "valid": true
104− },
105− {
106− "description": "an IPv6 address with out-of-range values",
107− "data": "12345::",
108− "valid": false
109− },
110− {
111− "description": "an IPv6 address with too many components",
112− "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1",
113− "valid": false
114− },
115− {
116− "description": "an IPv6 address containing illegal characters",
117− "data": "::laptop",
118− "valid": false
119− }
120− ]
121− },
122− {
123− "description": "validation of host names",
124− "schema": {"format": "hostname"},
125− "tests": [
126− {
127− "description": "a valid host name",
128− "data": "www.example.com",
129− "valid": true
130− },
131− {
132− "description": "a host name starting with an illegal character",
133− "data": "-a-host-name-that-starts-with--",
134− "valid": false
135− },
136− {
137− "description": "a host name containing illegal characters",
138− "data": "not_a_valid_host_name",
139− "valid": false
140− },
141− {
142− "description": "a host name with a component too long",
143− "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component",
144− "valid": false
145− }
146− ]
147− }
148−]
JSON-Schema-Test-Suite/tests/draft4/optional/zeroTerminatedFloats.jsondeleted−15
@@ -1,15 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft4/pattern.jsondeleted−34
@@ -1,34 +0,0 @@
1−[
2− {
3− "description": "pattern validation",
4− "schema": {"pattern": "^a*$"},
5− "tests": [
6− {
7− "description": "a matching pattern is valid",
8− "data": "aaa",
9− "valid": true
10− },
11− {
12− "description": "a non-matching pattern is invalid",
13− "data": "abc",
14− "valid": false
15− },
16− {
17− "description": "ignores non-strings",
18− "data": true,
19− "valid": true
20− }
21− ]
22− },
23− {
24− "description": "pattern is not anchored",
25− "schema": {"pattern": "a+"},
26− "tests": [
27− {
28− "description": "matches a substring",
29− "data": "xxaayy",
30− "valid": true
31− }
32− ]
33− }
34−]
JSON-Schema-Test-Suite/tests/draft4/patternProperties.jsondeleted−110
@@ -1,110 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft4/properties.jsondeleted−92
@@ -1,92 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft4/ref.jsondeleted−298
@@ -1,298 +0,0 @@
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 invalid",
90− "data": {"slash": "aoeu"},
91− "valid": false
92− },
93− {
94− "description": "tilda invalid",
95− "data": {"tilda": "aoeu"},
96− "valid": false
97− },
98− {
99− "description": "percent invalid",
100− "data": {"percent": "aoeu"},
101− "valid": false
102− },
103− {
104− "description": "slash valid",
105− "data": {"slash": 123},
106− "valid": true
107− },
108− {
109− "description": "tilda valid",
110− "data": {"tilda": 123},
111− "valid": true
112− },
113− {
114− "description": "percent valid",
115− "data": {"percent": 123},
116− "valid": true
117− }
118− ]
119− },
120− {
121− "description": "nested refs",
122− "schema": {
123− "definitions": {
124− "a": {"type": "integer"},
125− "b": {"$ref": "#/definitions/a"},
126− "c": {"$ref": "#/definitions/b"}
127− },
128− "$ref": "#/definitions/c"
129− },
130− "tests": [
131− {
132− "description": "nested ref valid",
133− "data": 5,
134− "valid": true
135− },
136− {
137− "description": "nested ref invalid",
138− "data": "a",
139− "valid": false
140− }
141− ]
142− },
143− {
144− "description": "ref overrides any sibling keywords",
145− "schema": {
146− "definitions": {
147− "reffed": {
148− "type": "array"
149− }
150− },
151− "properties": {
152− "foo": {
153− "$ref": "#/definitions/reffed",
154− "maxItems": 2
155− }
156− }
157− },
158− "tests": [
159− {
160− "description": "ref valid",
161− "data": { "foo": [] },
162− "valid": true
163− },
164− {
165− "description": "ref valid, maxItems ignored",
166− "data": { "foo": [ 1, 2, 3] },
167− "valid": true
168− },
169− {
170− "description": "ref invalid",
171− "data": { "foo": "string" },
172− "valid": false
173− }
174− ]
175− },
176− {
177− "description": "remote ref, containing refs itself",
178− "schema": {"$ref": "http://json-schema.org/draft-04/schema#"},
179− "tests": [
180− {
181− "description": "remote ref valid",
182− "data": {"minLength": 1},
183− "valid": true
184− },
185− {
186− "description": "remote ref invalid",
187− "data": {"minLength": -1},
188− "valid": false
189− }
190− ]
191− },
192− {
193− "description": "property named $ref that is not a reference",
194− "schema": {
195− "properties": {
196− "$ref": {"type": "string"}
197− }
198− },
199− "tests": [
200− {
201− "description": "property named $ref valid",
202− "data": {"$ref": "a"},
203− "valid": true
204− },
205− {
206− "description": "property named $ref invalid",
207− "data": {"$ref": 2},
208− "valid": false
209− }
210− ]
211− },
212− {
213− "description": "Recursive references between schemas",
214− "schema": {
215− "description": "tree of nodes",
216− "type": "object",
217− "properties": {
218− "meta": {"type": "string"},
219− "nodes": {
220− "type": "array",
221− "items": {"$ref": "#/definitions/node"}
222− }
223− },
224− "required": ["meta", "nodes"],
225− "definitions": {
226− "node": {
227− "description": "node",
228− "type": "object",
229− "properties": {
230− "value": {"type": "number"},
231− "subtree": {"$ref": "#"}
232− },
233− "required": ["value"]
234− }
235− }
236− },
237− "tests": [
238− {
239− "description": "valid tree",
240− "data": {
241− "meta": "root",
242− "nodes": [
243− {
244− "value": 1,
245− "subtree": {
246− "meta": "child",
247− "nodes": [
248− {"value": 1.1},
249− {"value": 1.2}
250− ]
251− }
252− },
253− {
254− "value": 2,
255− "subtree": {
256− "meta": "child",
257− "nodes": [
258− {"value": 2.1},
259− {"value": 2.2}
260− ]
261− }
262− }
263− ]
264− },
265− "valid": true
266− },
267− {
268− "description": "invalid tree",
269− "data": {
270− "meta": "root",
271− "nodes": [
272− {
273− "value": 1,
274− "subtree": {
275− "meta": "child",
276− "nodes": [
277− {"value": "string is invalid"},
278− {"value": 1.2}
279− ]
280− }
281− },
282− {
283− "value": 2,
284− "subtree": {
285− "meta": "child",
286− "nodes": [
287− {"value": 2.1},
288− {"value": 2.2}
289− ]
290− }
291− }
292− ]
293− },
294− "valid": false
295− }
296− ]
297− }
298−]
JSON-Schema-Test-Suite/tests/draft4/refRemote.jsondeleted−171
@@ -1,171 +0,0 @@
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": "base URI change",
54− "schema": {
55− "id": "http://localhost:1234/",
56− "items": {
57− "id": "folder/",
58− "items": {"$ref": "folderInteger.json"}
59− }
60− },
61− "tests": [
62− {
63− "description": "base URI change ref valid",
64− "data": [[1]],
65− "valid": true
66− },
67− {
68− "description": "base URI change ref invalid",
69− "data": [["a"]],
70− "valid": false
71− }
72− ]
73− },
74− {
75− "description": "base URI change - change folder",
76− "schema": {
77− "id": "http://localhost:1234/scope_change_defs1.json",
78− "type" : "object",
79− "properties": {
80− "list": {"$ref": "#/definitions/baz"}
81− },
82− "definitions": {
83− "baz": {
84− "id": "folder/",
85− "type": "array",
86− "items": {"$ref": "folderInteger.json"}
87− }
88− }
89− },
90− "tests": [
91− {
92− "description": "number is valid",
93− "data": {"list": [1]},
94− "valid": true
95− },
96− {
97− "description": "string is invalid",
98− "data": {"list": ["a"]},
99− "valid": false
100− }
101− ]
102− },
103− {
104− "description": "base URI change - change folder in subschema",
105− "schema": {
106− "id": "http://localhost:1234/scope_change_defs2.json",
107− "type" : "object",
108− "properties": {
109− "list": {"$ref": "#/definitions/baz/definitions/bar"}
110− },
111− "definitions": {
112− "baz": {
113− "id": "folder/",
114− "definitions": {
115− "bar": {
116− "type": "array",
117− "items": {"$ref": "folderInteger.json"}
118− }
119− }
120− }
121− }
122− },
123− "tests": [
124− {
125− "description": "number is valid",
126− "data": {"list": [1]},
127− "valid": true
128− },
129− {
130− "description": "string is invalid",
131− "data": {"list": ["a"]},
132− "valid": false
133− }
134− ]
135− },
136− {
137− "description": "root ref in remote ref",
138− "schema": {
139− "id": "http://localhost:1234/object",
140− "type": "object",
141− "properties": {
142− "name": {"$ref": "name.json#/definitions/orNull"}
143− }
144− },
145− "tests": [
146− {
147− "description": "string is valid",
148− "data": {
149− "name": "foo"
150− },
151− "valid": true
152− },
153− {
154− "description": "null is valid",
155− "data": {
156− "name": null
157− },
158− "valid": true
159− },
160− {
161− "description": "object is invalid",
162− "data": {
163− "name": {
164− "name": null
165− }
166− },
167− "valid": false
168− }
169− ]
170− }
171−]
JSON-Schema-Test-Suite/tests/draft4/required.jsondeleted−44
@@ -1,44 +0,0 @@
1−[
2− {
3− "description": "required validation",
4− "schema": {
5− "properties": {
6− "foo": {},
7− "bar": {}
8− },
9− "required": ["foo"]
10− },
11− "tests": [
12− {
13− "description": "present required property is valid",
14− "data": {"foo": 1},
15− "valid": true
16− },
17− {
18− "description": "non-present required property is invalid",
19− "data": {"bar": 1},
20− "valid": false
21− },
22− {
23− "description": "ignores non-objects",
24− "data": 12,
25− "valid": true
26− }
27− ]
28− },
29− {
30− "description": "required default validation",
31− "schema": {
32− "properties": {
33− "foo": {}
34− }
35− },
36− "tests": [
37− {
38− "description": "not required by default",
39− "data": {},
40− "valid": true
41− }
42− ]
43− }
44−]
JSON-Schema-Test-Suite/tests/draft4/type.jsondeleted−345
@@ -1,345 +0,0 @@
1−[
2− {
3− "description": "integer type matches integers",
4− "schema": {"type": "integer"},
5− "tests": [
6− {
7− "description": "an integer is an integer",
8− "data": 1,
9− "valid": true
10− },
11− {
12− "description": "a float is not an integer",
13− "data": 1.1,
14− "valid": false
15− },
16− {
17− "description": "a string is not an integer",
18− "data": "foo",
19− "valid": false
20− },
21− {
22− "description": "a string is still not an integer, even if it looks like one",
23− "data": "1",
24− "valid": false
25− },
26− {
27− "description": "an object is not an integer",
28− "data": {},
29− "valid": false
30− },
31− {
32− "description": "an array is not an integer",
33− "data": [],
34− "valid": false
35− },
36− {
37− "description": "a boolean is not an integer",
38− "data": true,
39− "valid": false
40− },
41− {
42− "description": "null is not an integer",
43− "data": null,
44− "valid": false
45− }
46− ]
47− },
48− {
49− "description": "number type matches numbers",
50− "schema": {"type": "number"},
51− "tests": [
52− {
53− "description": "an integer is a number",
54− "data": 1,
55− "valid": true
56− },
57− {
58− "description": "a float is a number",
59− "data": 1.1,
60− "valid": true
61− },
62− {
63− "description": "a string is not a number",
64− "data": "foo",
65− "valid": false
66− },
67− {
68− "description": "a string is still not a number, even if it looks like one",
69− "data": "1",
70− "valid": false
71− },
72− {
73− "description": "an object is not a number",
74− "data": {},
75− "valid": false
76− },
77− {
78− "description": "an array is not a number",
79− "data": [],
80− "valid": false
81− },
82− {
83− "description": "a boolean is not a number",
84− "data": true,
85− "valid": false
86− },
87− {
88− "description": "null is not a number",
89− "data": null,
90− "valid": false
91− }
92− ]
93− },
94− {
95− "description": "string type matches strings",
96− "schema": {"type": "string"},
97− "tests": [
98− {
99− "description": "1 is not a string",
100− "data": 1,
101− "valid": false
102− },
103− {
104− "description": "a float is not a string",
105− "data": 1.1,
106− "valid": false
107− },
108− {
109− "description": "a string is a string",
110− "data": "foo",
111− "valid": true
112− },
113− {
114− "description": "a string is still a string, even if it looks like a number",
115− "data": "1",
116− "valid": true
117− },
118− {
119− "description": "an object is not a string",
120− "data": {},
121− "valid": false
122− },
123− {
124− "description": "an array is not a string",
125− "data": [],
126− "valid": false
127− },
128− {
129− "description": "a boolean is not a string",
130− "data": true,
131− "valid": false
132− },
133− {
134− "description": "null is not a string",
135− "data": null,
136− "valid": false
137− }
138− ]
139− },
140− {
141− "description": "object type matches objects",
142− "schema": {"type": "object"},
143− "tests": [
144− {
145− "description": "an integer is not an object",
146− "data": 1,
147− "valid": false
148− },
149− {
150− "description": "a float is not an object",
151− "data": 1.1,
152− "valid": false
153− },
154− {
155− "description": "a string is not an object",
156− "data": "foo",
157− "valid": false
158− },
159− {
160− "description": "an object is an object",
161− "data": {},
162− "valid": true
163− },
164− {
165− "description": "an array is not an object",
166− "data": [],
167− "valid": false
168− },
169− {
170− "description": "a boolean is not an object",
171− "data": true,
172− "valid": false
173− },
174− {
175− "description": "null is not an object",
176− "data": null,
177− "valid": false
178− }
179− ]
180− },
181− {
182− "description": "array type matches arrays",
183− "schema": {"type": "array"},
184− "tests": [
185− {
186− "description": "an integer is not an array",
187− "data": 1,
188− "valid": false
189− },
190− {
191− "description": "a float is not an array",
192− "data": 1.1,
193− "valid": false
194− },
195− {
196− "description": "a string is not an array",
197− "data": "foo",
198− "valid": false
199− },
200− {
201− "description": "an object is not an array",
202− "data": {},
203− "valid": false
204− },
205− {
206− "description": "an array is an array",
207− "data": [],
208− "valid": true
209− },
210− {
211− "description": "a boolean is not an array",
212− "data": true,
213− "valid": false
214− },
215− {
216− "description": "null is not an array",
217− "data": null,
218− "valid": false
219− }
220− ]
221− },
222− {
223− "description": "boolean type matches booleans",
224− "schema": {"type": "boolean"},
225− "tests": [
226− {
227− "description": "an integer is not a boolean",
228− "data": 1,
229− "valid": false
230− },
231− {
232− "description": "a float is not a boolean",
233− "data": 1.1,
234− "valid": false
235− },
236− {
237− "description": "a string is not a boolean",
238− "data": "foo",
239− "valid": false
240− },
241− {
242− "description": "an object is not a boolean",
243− "data": {},
244− "valid": false
245− },
246− {
247− "description": "an array is not a boolean",
248− "data": [],
249− "valid": false
250− },
251− {
252− "description": "a boolean is a boolean",
253− "data": true,
254− "valid": true
255− },
256− {
257− "description": "null is not a boolean",
258− "data": null,
259− "valid": false
260− }
261− ]
262− },
263− {
264− "description": "null type matches only the null object",
265− "schema": {"type": "null"},
266− "tests": [
267− {
268− "description": "an integer is not null",
269− "data": 1,
270− "valid": false
271− },
272− {
273− "description": "a float is not null",
274− "data": 1.1,
275− "valid": false
276− },
277− {
278− "description": "a string is not null",
279− "data": "foo",
280− "valid": false
281− },
282− {
283− "description": "an object is not null",
284− "data": {},
285− "valid": false
286− },
287− {
288− "description": "an array is not null",
289− "data": [],
290− "valid": false
291− },
292− {
293− "description": "a boolean is not null",
294− "data": true,
295− "valid": false
296− },
297− {
298− "description": "null is null",
299− "data": null,
300− "valid": true
301− }
302− ]
303− },
304− {
305− "description": "multiple types can be specified in an array",
306− "schema": {"type": ["integer", "string"]},
307− "tests": [
308− {
309− "description": "an integer is valid",
310− "data": 1,
311− "valid": true
312− },
313− {
314− "description": "a string is valid",
315− "data": "foo",
316− "valid": true
317− },
318− {
319− "description": "a float is invalid",
320− "data": 1.1,
321− "valid": false
322− },
323− {
324− "description": "an object is invalid",
325− "data": {},
326− "valid": false
327− },
328− {
329− "description": "an array is invalid",
330− "data": [],
331− "valid": false
332− },
333− {
334− "description": "a boolean is invalid",
335− "data": true,
336− "valid": false
337− },
338− {
339− "description": "null is invalid",
340− "data": null,
341− "valid": false
342− }
343− ]
344− }
345−]
JSON-Schema-Test-Suite/tests/draft4/uniqueItems.jsondeleted−79
@@ -1,79 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft6/additionalItems.jsondeleted−87
@@ -1,87 +0,0 @@
1−[
2− {
3− "description": "additionalItems as schema",
4− "schema": {
5− "items": [{}],
6− "additionalItems": {"type": "integer"}
7− },
8− "tests": [
9− {
10− "description": "additional items match schema",
11− "data": [ null, 2, 3, 4 ],
12− "valid": true
13− },
14− {
15− "description": "additional items do not match schema",
16− "data": [ null, 2, 3, "foo" ],
17− "valid": false
18− }
19− ]
20− },
21− {
22− "description": "items is schema, no additionalItems",
23− "schema": {
24− "items": {},
25− "additionalItems": false
26− },
27− "tests": [
28− {
29− "description": "all items match schema",
30− "data": [ 1, 2, 3, 4, 5 ],
31− "valid": true
32− }
33− ]
34− },
35− {
36− "description": "array of items with no additionalItems",
37− "schema": {
38− "items": [{}, {}, {}],
39− "additionalItems": false
40− },
41− "tests": [
42− {
43− "description": "fewer number of items present",
44− "data": [ 1, 2 ],
45− "valid": true
46− },
47− {
48− "description": "equal number of items present",
49− "data": [ 1, 2, 3 ],
50− "valid": true
51− },
52− {
53− "description": "additional items are not permitted",
54− "data": [ 1, 2, 3, 4 ],
55− "valid": false
56− }
57− ]
58− },
59− {
60− "description": "additionalItems as false without items",
61− "schema": {"additionalItems": false},
62− "tests": [
63− {
64− "description":
65− "items defaults to empty schema so everything is valid",
66− "data": [ 1, 2, 3, 4, 5 ],
67− "valid": true
68− },
69− {
70− "description": "ignores non-arrays",
71− "data": {"foo" : "bar"},
72− "valid": true
73− }
74− ]
75− },
76− {
77− "description": "additionalItems are allowed by default",
78− "schema": {"items": [{"type": "integer"}]},
79− "tests": [
80− {
81− "description": "only the first item is validated",
82− "data": [1, "foo", false],
83− "valid": true
84− }
85− ]
86− }
87−]
JSON-Schema-Test-Suite/tests/draft6/additionalProperties.jsondeleted−88
@@ -1,88 +0,0 @@
1−[
2− {
3− "description":
4− "additionalProperties being false does not allow other properties",
5− "schema": {
6− "properties": {"foo": {}, "bar": {}},
7− "patternProperties": { "^v": {} },
8− "additionalProperties": false
9− },
10− "tests": [
11− {
12− "description": "no additional properties is valid",
13− "data": {"foo": 1},
14− "valid": true
15− },
16− {
17− "description": "an additional property is invalid",
18− "data": {"foo" : 1, "bar" : 2, "quux" : "boom"},
19− "valid": false
20− },
21− {
22− "description": "ignores non-objects",
23− "data": [1, 2, 3],
24− "valid": true
25− },
26− {
27− "description": "patternProperties are not additional properties",
28− "data": {"foo":1, "vroom": 2},
29− "valid": true
30− }
31− ]
32− },
33− {
34− "description":
35− "additionalProperties allows a schema which should validate",
36− "schema": {
37− "properties": {"foo": {}, "bar": {}},
38− "additionalProperties": {"type": "boolean"}
39− },
40− "tests": [
41− {
42− "description": "no additional properties is valid",
43− "data": {"foo": 1},
44− "valid": true
45− },
46− {
47− "description": "an additional valid property is valid",
48− "data": {"foo" : 1, "bar" : 2, "quux" : true},
49− "valid": true
50− },
51− {
52− "description": "an additional invalid property is invalid",
53− "data": {"foo" : 1, "bar" : 2, "quux" : 12},
54− "valid": false
55− }
56− ]
57− },
58− {
59− "description":
60− "additionalProperties can exist by itself",
61− "schema": {
62− "additionalProperties": {"type": "boolean"}
63− },
64− "tests": [
65− {
66− "description": "an additional valid property is valid",
67− "data": {"foo" : true},
68− "valid": true
69− },
70− {
71− "description": "an additional invalid property is invalid",
72− "data": {"foo" : 1},
73− "valid": false
74− }
75− ]
76− },
77− {
78− "description": "additionalProperties are allowed by default",
79− "schema": {"properties": {"foo": {}, "bar": {}}},
80− "tests": [
81− {
82− "description": "additional properties are allowed",
83− "data": {"foo": 1, "bar": 2, "quux": true},
84− "valid": true
85− }
86− ]
87− }
88−]
JSON-Schema-Test-Suite/tests/draft6/allOf.jsondeleted−145
@@ -1,145 +0,0 @@
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− "description": "allOf with boolean schemas, all true",
114− "schema": {"allOf": [true, true]},
115− "tests": [
116− {
117− "description": "any value is valid",
118− "data": "foo",
119− "valid": true
120− }
121− ]
122− },
123− {
124− "description": "allOf with boolean schemas, some false",
125− "schema": {"allOf": [true, false]},
126− "tests": [
127− {
128− "description": "any value is invalid",
129− "data": "foo",
130− "valid": false
131− }
132− ]
133− },
134− {
135− "description": "allOf with boolean schemas, all false",
136− "schema": {"allOf": [false, false]},
137− "tests": [
138− {
139− "description": "any value is invalid",
140− "data": "foo",
141− "valid": false
142− }
143− ]
144− }
145−]
JSON-Schema-Test-Suite/tests/draft6/anyOf.jsondeleted−101
@@ -1,101 +0,0 @@
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− "description": "anyOf with boolean schemas, all true",
70− "schema": {"anyOf": [true, true]},
71− "tests": [
72− {
73− "description": "any value is valid",
74− "data": "foo",
75− "valid": true
76− }
77− ]
78− },
79− {
80− "description": "anyOf with boolean schemas, some true",
81− "schema": {"anyOf": [true, false]},
82− "tests": [
83− {
84− "description": "any value is valid",
85− "data": "foo",
86− "valid": true
87− }
88− ]
89− },
90− {
91− "description": "anyOf with boolean schemas, all false",
92− "schema": {"anyOf": [false, false]},
93− "tests": [
94− {
95− "description": "any value is invalid",
96− "data": "foo",
97− "valid": false
98− }
99− ]
100− }
101−]
JSON-Schema-Test-Suite/tests/draft6/boolean_schema.jsondeleted−104
@@ -1,104 +0,0 @@
1−[
2− {
3− "description": "boolean schema 'true'",
4− "schema": true,
5− "tests": [
6− {
7− "description": "number is valid",
8− "data": 1,
9− "valid": true
10− },
11− {
12− "description": "string is valid",
13− "data": "foo",
14− "valid": true
15− },
16− {
17− "description": "boolean true is valid",
18− "data": true,
19− "valid": true
20− },
21− {
22− "description": "boolean false is valid",
23− "data": false,
24− "valid": true
25− },
26− {
27− "description": "null is valid",
28− "data": null,
29− "valid": true
30− },
31− {
32− "description": "object is valid",
33− "data": {"foo": "bar"},
34− "valid": true
35− },
36− {
37− "description": "empty object is valid",
38− "data": {},
39− "valid": true
40− },
41− {
42− "description": "array is valid",
43− "data": ["foo"],
44− "valid": true
45− },
46− {
47− "description": "empty array is valid",
48− "data": [],
49− "valid": true
50− }
51− ]
52− },
53− {
54− "description": "boolean schema 'false'",
55− "schema": false,
56− "tests": [
57− {
58− "description": "number is invalid",
59− "data": 1,
60− "valid": false
61− },
62− {
63− "description": "string is invalid",
64− "data": "foo",
65− "valid": false
66− },
67− {
68− "description": "boolean true is invalid",
69− "data": true,
70− "valid": false
71− },
72− {
73− "description": "boolean false is invalid",
74− "data": false,
75− "valid": false
76− },
77− {
78− "description": "null is invalid",
79− "data": null,
80− "valid": false
81− },
82− {
83− "description": "object is invalid",
84− "data": {"foo": "bar"},
85− "valid": false
86− },
87− {
88− "description": "empty object is invalid",
89− "data": {},
90− "valid": false
91− },
92− {
93− "description": "array is invalid",
94− "data": ["foo"],
95− "valid": false
96− },
97− {
98− "description": "empty array is invalid",
99− "data": [],
100− "valid": false
101− }
102− ]
103− }
104−]
JSON-Schema-Test-Suite/tests/draft6/const.jsondeleted−65
@@ -1,65 +0,0 @@
1−[
2− {
3− "description": "const validation",
4− "schema": {"const": 2},
5− "tests": [
6− {
7− "description": "same value is valid",
8− "data": 2,
9− "valid": true
10− },
11− {
12− "description": "another value is invalid",
13− "data": 5,
14− "valid": false
15− },
16− {
17− "description": "another type is invalid",
18− "data": "a",
19− "valid": false
20− }
21− ]
22− },
23− {
24− "description": "const with object",
25− "schema": {"const": {"foo": "bar", "baz": "bax"}},
26− "tests": [
27− {
28− "description": "same object is valid",
29− "data": {"foo": "bar", "baz": "bax"},
30− "valid": true
31− },
32− {
33− "description": "same object with different property order is valid",
34− "data": {"baz": "bax", "foo": "bar"},
35− "valid": true
36− },
37− {
38− "description": "another object is invalid",
39− "data": {"foo": "bar"},
40− "valid": false
41− },
42− {
43− "description": "another type is invalid",
44− "data": [1, 2],
45− "valid": false
46− }
47− ]
48− },
49− {
50− "description": "const with null",
51− "schema": {"const": null},
52− "tests": [
53− {
54− "description": "null is valid",
55− "data": null,
56− "valid": true
57− },
58− {
59− "description": "not null is invalid",
60− "data": 0,
61− "valid": false
62− }
63− ]
64− }
65−]
JSON-Schema-Test-Suite/tests/draft6/contains.jsondeleted−95
@@ -1,95 +0,0 @@
1−[
2− {
3− "description": "contains keyword validation",
4− "schema": {
5− "contains": {"minimum": 5}
6− },
7− "tests": [
8− {
9− "description": "array with item matching schema (5) is valid",
10− "data": [3, 4, 5],
11− "valid": true
12− },
13− {
14− "description": "array with item matching schema (6) is valid",
15− "data": [3, 4, 6],
16− "valid": true
17− },
18− {
19− "description": "array with two items matching schema (5, 6) is valid",
20− "data": [3, 4, 5, 6],
21− "valid": true
22− },
23− {
24− "description": "array without items matching schema is invalid",
25− "data": [2, 3, 4],
26− "valid": false
27− },
28− {
29− "description": "empty array is invalid",
30− "data": [],
31− "valid": false
32− },
33− {
34− "description": "not array is valid",
35− "data": {},
36− "valid": true
37− }
38− ]
39− },
40− {
41− "description": "contains keyword with const keyword",
42− "schema": {
43− "contains": { "const": 5 }
44− },
45− "tests": [
46− {
47− "description": "array with item 5 is valid",
48− "data": [3, 4, 5],
49− "valid": true
50− },
51− {
52− "description": "array with two items 5 is valid",
53− "data": [3, 4, 5, 5],
54− "valid": true
55− },
56− {
57− "description": "array without item 5 is invalid",
58− "data": [1, 2, 3, 4],
59− "valid": false
60− }
61− ]
62− },
63− {
64− "description": "contains keyword with boolean schema true",
65− "schema": {"contains": true},
66− "tests": [
67− {
68− "description": "any non-empty array is valid",
69− "data": ["foo"],
70− "valid": true
71− },
72− {
73− "description": "empty array is invalid",
74− "data": [],
75− "valid": false
76− }
77− ]
78− },
79− {
80− "description": "contains keyword with boolean schema false",
81− "schema": {"contains": false},
82− "tests": [
83− {
84− "description": "any non-empty array is invalid",
85− "data": ["foo"],
86− "valid": false
87− },
88− {
89− "description": "empty array is invalid",
90− "data": [],
91− "valid": false
92− }
93− ]
94− }
95−]
JSON-Schema-Test-Suite/tests/draft6/default.jsondeleted−49
@@ -1,49 +0,0 @@
1−[
2− {
3− "description": "invalid type for default",
4− "schema": {
5− "properties": {
6− "foo": {
7− "type": "integer",
8− "default": []
9− }
10− }
11− },
12− "tests": [
13− {
14− "description": "valid when property is specified",
15− "data": {"foo": 13},
16− "valid": true
17− },
18− {
19− "description": "still valid when the invalid default is used",
20− "data": {},
21− "valid": true
22− }
23− ]
24− },
25− {
26− "description": "invalid string value for default",
27− "schema": {
28− "properties": {
29− "bar": {
30− "type": "string",
31− "minLength": 4,
32− "default": "bad"
33− }
34− }
35− },
36− "tests": [
37− {
38− "description": "valid when property is specified",
39− "data": {"bar": "good"},
40− "valid": true
41− },
42− {
43− "description": "still valid when the invalid default is used",
44− "data": {},
45− "valid": true
46− }
47− ]
48− }
49−]
JSON-Schema-Test-Suite/tests/draft6/definitions.jsondeleted−32
@@ -1,32 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft6/dependencies.jsondeleted−162
@@ -1,162 +0,0 @@
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": "dependencies with empty array",
37− "schema": {
38− "dependencies": {"bar": []}
39− },
40− "tests": [
41− {
42− "description": "empty object",
43− "data": {},
44− "valid": true
45− },
46− {
47− "description": "object with one property",
48− "data": {"bar": 2},
49− "valid": true
50− }
51− ]
52− },
53− {
54− "description": "multiple dependencies",
55− "schema": {
56− "dependencies": {"quux": ["foo", "bar"]}
57− },
58− "tests": [
59− {
60− "description": "neither",
61− "data": {},
62− "valid": true
63− },
64− {
65− "description": "nondependants",
66− "data": {"foo": 1, "bar": 2},
67− "valid": true
68− },
69− {
70− "description": "with dependencies",
71− "data": {"foo": 1, "bar": 2, "quux": 3},
72− "valid": true
73− },
74− {
75− "description": "missing dependency",
76− "data": {"foo": 1, "quux": 2},
77− "valid": false
78− },
79− {
80− "description": "missing other dependency",
81− "data": {"bar": 1, "quux": 2},
82− "valid": false
83− },
84− {
85− "description": "missing both dependencies",
86− "data": {"quux": 1},
87− "valid": false
88− }
89− ]
90− },
91− {
92− "description": "multiple dependencies subschema",
93− "schema": {
94− "dependencies": {
95− "bar": {
96− "properties": {
97− "foo": {"type": "integer"},
98− "bar": {"type": "integer"}
99− }
100− }
101− }
102− },
103− "tests": [
104− {
105− "description": "valid",
106− "data": {"foo": 1, "bar": 2},
107− "valid": true
108− },
109− {
110− "description": "no dependency",
111− "data": {"foo": "quux"},
112− "valid": true
113− },
114− {
115− "description": "wrong type",
116− "data": {"foo": "quux", "bar": 2},
117− "valid": false
118− },
119− {
120− "description": "wrong type other",
121− "data": {"foo": 2, "bar": "quux"},
122− "valid": false
123− },
124− {
125− "description": "wrong type both",
126− "data": {"foo": "quux", "bar": "quux"},
127− "valid": false
128− }
129− ]
130− },
131− {
132− "description": "dependencies with boolean subschemas",
133− "schema": {
134− "dependencies": {
135− "foo": true,
136− "bar": false
137− }
138− },
139− "tests": [
140− {
141− "description": "object with property having schema true is valid",
142− "data": {"foo": 1},
143− "valid": true
144− },
145− {
146− "description": "object with property having schema false is invalid",
147− "data": {"bar": 2},
148− "valid": false
149− },
150− {
151− "description": "object with both properties is invalid",
152− "data": {"foo": 1, "bar": 2},
153− "valid": false
154− },
155− {
156− "description": "empty object is valid",
157− "data": {},
158− "valid": true
159− }
160− ]
161− }
162−]
JSON-Schema-Test-Suite/tests/draft6/enum.jsondeleted−72
@@ -1,72 +0,0 @@
1−[
2− {
3− "description": "simple enum validation",
4− "schema": {"enum": [1, 2, 3]},
5− "tests": [
6− {
7− "description": "one of the enum is valid",
8− "data": 1,
9− "valid": true
10− },
11− {
12− "description": "something else is invalid",
13− "data": 4,
14− "valid": false
15− }
16− ]
17− },
18− {
19− "description": "heterogeneous enum validation",
20− "schema": {"enum": [6, "foo", [], true, {"foo": 12}]},
21− "tests": [
22− {
23− "description": "one of the enum is valid",
24− "data": [],
25− "valid": true
26− },
27− {
28− "description": "something else is invalid",
29− "data": null,
30− "valid": false
31− },
32− {
33− "description": "objects are deep compared",
34− "data": {"foo": false},
35− "valid": false
36− }
37− ]
38− },
39− {
40− "description": "enums in properties",
41− "schema": {
42− "type":"object",
43− "properties": {
44− "foo": {"enum":["foo"]},
45− "bar": {"enum":["bar"]}
46− },
47− "required": ["bar"]
48− },
49− "tests": [
50− {
51− "description": "both properties are valid",
52− "data": {"foo":"foo", "bar":"bar"},
53− "valid": true
54− },
55− {
56− "description": "missing optional property is valid",
57− "data": {"bar":"bar"},
58− "valid": true
59− },
60− {
61− "description": "missing required property is invalid",
62− "data": {"foo":"foo"},
63− "valid": false
64− },
65− {
66− "description": "missing all properties is invalid",
67− "data": {},
68− "valid": false
69− }
70− ]
71− }
72−]
JSON-Schema-Test-Suite/tests/draft6/exclusiveMaximum.jsondeleted−30
@@ -1,30 +0,0 @@
1−[
2− {
3− "description": "exclusiveMaximum validation",
4− "schema": {
5− "exclusiveMaximum": 3.0
6− },
7− "tests": [
8− {
9− "description": "below the exclusiveMaximum is valid",
10− "data": 2.2,
11− "valid": true
12− },
13− {
14− "description": "boundary point is invalid",
15− "data": 3.0,
16− "valid": false
17− },
18− {
19− "description": "above the exclusiveMaximum is invalid",
20− "data": 3.5,
21− "valid": false
22− },
23− {
24− "description": "ignores non-numbers",
25− "data": "x",
26− "valid": true
27− }
28− ]
29− }
30−]
JSON-Schema-Test-Suite/tests/draft6/exclusiveMinimum.jsondeleted−30
@@ -1,30 +0,0 @@
1−[
2− {
3− "description": "exclusiveMinimum validation",
4− "schema": {
5− "exclusiveMinimum": 1.1
6− },
7− "tests": [
8− {
9− "description": "above the exclusiveMinimum is valid",
10− "data": 1.2,
11− "valid": true
12− },
13− {
14− "description": "boundary point is invalid",
15− "data": 1.1,
16− "valid": false
17− },
18− {
19− "description": "below the exclusiveMinimum is invalid",
20− "data": 0.6,
21− "valid": false
22− },
23− {
24− "description": "ignores non-numbers",
25− "data": "x",
26− "valid": true
27− }
28− ]
29− }
30−]
JSON-Schema-Test-Suite/tests/draft6/items.jsondeleted−133
@@ -1,133 +0,0 @@
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− "description": "JavaScript pseudo-array is valid",
25− "data": {
26− "0": "invalid",
27− "length": 1
28− },
29− "valid": true
30− }
31− ]
32− },
33− {
34− "description": "an array of schemas for items",
35− "schema": {
36− "items": [
37− {"type": "integer"},
38− {"type": "string"}
39− ]
40− },
41− "tests": [
42− {
43− "description": "correct types",
44− "data": [ 1, "foo" ],
45− "valid": true
46− },
47− {
48− "description": "wrong types",
49− "data": [ "foo", 1 ],
50− "valid": false
51− },
52− {
53− "description": "incomplete array of items",
54− "data": [ 1 ],
55− "valid": true
56− },
57− {
58− "description": "array with additional items",
59− "data": [ 1, "foo", true ],
60− "valid": true
61− },
62− {
63− "description": "empty array",
64− "data": [ ],
65− "valid": true
66− },
67− {
68− "description": "JavaScript pseudo-array is valid",
69− "data": {
70− "0": "invalid",
71− "1": "valid",
72− "length": 2
73− },
74− "valid": true
75− }
76− ]
77− },
78− {
79− "description": "items with boolean schema (true)",
80− "schema": {"items": true},
81− "tests": [
82− {
83− "description": "any array is valid",
84− "data": [ 1, "foo", true ],
85− "valid": true
86− },
87− {
88− "description": "empty array is valid",
89− "data": [],
90− "valid": true
91− }
92− ]
93− },
94− {
95− "description": "items with boolean schema (false)",
96− "schema": {"items": false},
97− "tests": [
98− {
99− "description": "any non-empty array is invalid",
100− "data": [ 1, "foo", true ],
101− "valid": false
102− },
103− {
104− "description": "empty array is valid",
105− "data": [],
106− "valid": true
107− }
108− ]
109− },
110− {
111− "description": "items with boolean schemas",
112− "schema": {
113− "items": [true, false]
114− },
115− "tests": [
116− {
117− "description": "array with one item is valid",
118− "data": [ 1 ],
119− "valid": true
120− },
121− {
122− "description": "array with two items is invalid",
123− "data": [ 1, "foo" ],
124− "valid": false
125− },
126− {
127− "description": "empty array is valid",
128− "data": [],
129− "valid": true
130− }
131− ]
132− }
133−]
JSON-Schema-Test-Suite/tests/draft6/maxItems.jsondeleted−28
@@ -1,28 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft6/maxLength.jsondeleted−33
@@ -1,33 +0,0 @@
1−[
2− {
3− "description": "maxLength validation",
4− "schema": {"maxLength": 2},
5− "tests": [
6− {
7− "description": "shorter is valid",
8− "data": "f",
9− "valid": true
10− },
11− {
12− "description": "exact length is valid",
13− "data": "fo",
14− "valid": true
15− },
16− {
17− "description": "too long is invalid",
18− "data": "foo",
19− "valid": false
20− },
21− {
22− "description": "ignores non-strings",
23− "data": 100,
24− "valid": true
25− },
26− {
27− "description": "two supplementary Unicode code points is long enough",
28− "data": "\uD83D\uDCA9\uD83D\uDCA9",
29− "valid": true
30− }
31− ]
32− }
33−]
JSON-Schema-Test-Suite/tests/draft6/maxProperties.jsondeleted−28
@@ -1,28 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft6/maximum.jsondeleted−28
@@ -1,28 +0,0 @@
1−[
2− {
3− "description": "maximum validation",
4− "schema": {"maximum": 3.0},
5− "tests": [
6− {
7− "description": "below the maximum is valid",
8− "data": 2.6,
9− "valid": true
10− },
11− {
12− "description": "boundary point is valid",
13− "data": 3.0,
14− "valid": true
15− },
16− {
17− "description": "above the maximum is invalid",
18− "data": 3.5,
19− "valid": false
20− },
21− {
22− "description": "ignores non-numbers",
23− "data": "x",
24− "valid": true
25− }
26− ]
27− }
28−]
JSON-Schema-Test-Suite/tests/draft6/minItems.jsondeleted−28
@@ -1,28 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft6/minLength.jsondeleted−33
@@ -1,33 +0,0 @@
1−[
2− {
3− "description": "minLength validation",
4− "schema": {"minLength": 2},
5− "tests": [
6− {
7− "description": "longer is valid",
8− "data": "foo",
9− "valid": true
10− },
11− {
12− "description": "exact length is valid",
13− "data": "fo",
14− "valid": true
15− },
16− {
17− "description": "too short is invalid",
18− "data": "f",
19− "valid": false
20− },
21− {
22− "description": "ignores non-strings",
23− "data": 1,
24− "valid": true
25− },
26− {
27− "description": "one supplementary Unicode code point is not long enough",
28− "data": "\uD83D\uDCA9",
29− "valid": false
30− }
31− ]
32− }
33−]
JSON-Schema-Test-Suite/tests/draft6/minProperties.jsondeleted−28
@@ -1,28 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft6/minimum.jsondeleted−28
@@ -1,28 +0,0 @@
1−[
2− {
3− "description": "minimum validation",
4− "schema": {"minimum": 1.1},
5− "tests": [
6− {
7− "description": "above the minimum is valid",
8− "data": 2.6,
9− "valid": true
10− },
11− {
12− "description": "boundary point is valid",
13− "data": 1.1,
14− "valid": true
15− },
16− {
17− "description": "below the minimum is invalid",
18− "data": 0.6,
19− "valid": false
20− },
21− {
22− "description": "ignores non-numbers",
23− "data": "x",
24− "valid": true
25− }
26− ]
27− }
28−]
JSON-Schema-Test-Suite/tests/draft6/multipleOf.jsondeleted−60
@@ -1,60 +0,0 @@
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−]
JSON-Schema-Test-Suite/tests/draft6/not.jsondeleted−117
@@ -1,117 +0,0 @@
1−[
2− {
3− "description": "not",
4− "schema": {
5− "not": {"type": "integer"}
6− },
7− "tests": [
8− {
9− "description": "allowed",
10− "data": "foo",
11− "valid": true
12− },
13− {
14− "description": "disallowed",
15− "data": 1,
16− "valid": false
17− }
18− ]
19− },
20− {
21− "description": "not multiple types",
22− "schema": {
23− "not": {"type": ["integer", "boolean"]}
24− },
25− "tests": [
26− {
27− "description": "valid",
28− "data": "foo",
29− "valid": true
30− },
31− {
32− "description": "mismatch",
33− "data": 1,
34− "valid": false
35− },
36− {
37− "description": "other mismatch",
38− "data": true,
39− "valid": false
40− }
41− ]
42− },
43− {
44− "description": "not more complex schema",
45− "schema": {
46− "not": {
47− "type": "object",
48− "properties": {
49− "foo": {
50− "type": "string"
51− }
52− }
53− }
54− },
55− "tests": [
56− {
57− "description": "match",
58− "data": 1,
59− "valid": true
60− },
61− {
62− "description": "other match",
63− "data": {"foo": 1},
64− "valid": true
65− },
66− {
67− "description": "mismatch",
68− "data": {"foo": "bar"},
69− "valid": false
70− }
71− ]
72− },
73− {
74− "description": "forbidden property",
75− "schema": {
76− "properties": {
77− "foo": {
78− "not": {}
79− }
80− }
81− },
82− "tests": [
83− {
84− "description": "property present",
85− "data": {"foo": 1, "bar": 2},
86− "valid": false
87− },
88− {
89− "description": "property absent",
90− "data": {"bar": 1, "baz": 2},
91− "valid": true
92− }
93− ]
94− },
95− {
96− "description": "not with boolean schema true",
97− "schema": {"not": true},
98− "tests": [
99− {
100− "description": "any value is invalid",
101− "data": "foo",
102− "valid": false
103− }
104− ]
105− },
106− {
107− "description": "not with boolean schema false",
108− "schema": {"not": false},
109− "tests": [
110− {
111− "description": "any value is valid",
112− "data": "foo",
113− "valid": true
114− }
115− ]
116− }
117−]
JSON-Schema-Test-Suite/tests/draft6/oneOf.jsondeleted−112
@@ -1,112 +0,0 @@
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− "description": "oneOf with boolean schemas, all true",
70− "schema": {"oneOf": [true, true, true]},
71− "tests": [
72− {
73− "description": "any value is invalid",
74− "data": "foo",
75− "valid": false
76− }
77− ]
78− },
79− {
80− "description": "oneOf with boolean schemas, one true",
81− "schema": {"oneOf": [true, false, false]},
82− "tests": [
83− {
84− "description": "any value is valid",
85− "data": "foo",
86− "valid": true
87− }
88− ]
89− },
90− {
91− "description": "oneOf with boolean schemas, more than one true",
92− "schema": {"oneOf": [true, true, false]},
93− "tests": [
94− {
95− "description": "any value is invalid",
96− "data": "foo",
97− "valid": false
98− }
99− ]
100− },
101− {
102− "description": "oneOf with boolean schemas, all false",
103− "schema": {"oneOf": [false, false, false]},
104− "tests": [
105− {
106− "description": "any value is invalid",
107− "data": "foo",
108− "valid": false
109− }
110− ]
111− }
112−]
JSON-Schema-Test-Suite/tests/draft6/optional/bignum.jsondeleted−105
@@ -1,105 +0,0 @@
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": "integer",
26− "schema": {"type": "integer"},
27− "tests": [
28− {
29− "description": "a negative bignum is an integer",
30− "data": -12345678910111213141516171819202122232425262728293031,
31− "valid": true
32− }
33− ]
34− },
35− {
36− "description": "number",
37− "schema": {"type": "number"},
38− "tests": [
39− {
40− "description": "a negative bignum is a number",
41− "data": -98249283749234923498293171823948729348710298301928331,
42− "valid": true
43− }
44− ]
45− },
46− {
47− "description": "string",
48− "schema": {"type": "string"},
49− "tests": [
50− {
51− "description": "a bignum is not a string",
52− "data": 98249283749234923498293171823948729348710298301928331,
53− "valid": false
54− }
55− ]
56− },
57− {
58− "description": "integer comparison",
59− "schema": {"maximum": 18446744073709551615},
60− "tests": [
61− {
62− "description": "comparison works for high numbers",
63− "data": 18446744073709551600,
64− "valid": true
65− }
66− ]
67− },
68− {
69− "description": "float comparison with high precision",
70− "schema": {
71− "exclusiveMaximum": 972783798187987123879878123.18878137
72− },
73− "tests": [
74− {
75− "description": "comparison works for high numbers",
76− "data": 972783798187987123879878123.188781371,
77− "valid": false
78− }
79− ]
80− },
81− {
82− "description": "integer comparison",
83− "schema": {"minimum": -18446744073709551615},
84− "tests": [
85− {
86− "description": "comparison works for very negative numbers",
87− "data": -18446744073709551600,
88− "valid": true
89− }
90− ]
91− },
92− {
93− "description": "float comparison with high precision on negative numbers",
94− "schema": {
95− "exclusiveMinimum": -972783798187987123879878123.18878137
96− },
97− "tests": [
98− {
99− "description": "comparison works for very negative numbers",
100− "data": -972783798187987123879878123.188781371,
101− "valid": false
102− }
103− ]
104− }
105−]
JSON-Schema-Test-Suite/tests/draft6/optional/ecmascript-regex.jsondeleted−13
@@ -1,13 +0,0 @@
1−[
2− {
3− "description": "ECMA 262 regex non-compliance",
4− "schema": { "format": "regex" },
5− "tests": [
6− {
7− "description": "ECMA 262 has no support for \\Z anchor from .NET",
8− "data": "^\\S(|(.|\\n)*\\S)\\Z",
9− "valid": false
10− }
11− ]
12− }
13−]
JSON-Schema-Test-Suite/tests/draft6/optional/format.jsondeleted−148
@@ -1,148 +0,0 @@
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 invalid protocol-relative URI Reference",
34− "data": "//foo.bar/?baz=qux#quux",
35− "valid": false
36− },
37− {
38− "description": "an invalid URI",
39− "data": "\\\\WINDOWS\\fileshare",
40− "valid": false
41− },
42− {
43− "description": "an invalid URI though valid URI reference",
44− "data": "abc",
45− "valid": false
46− }
47− ]
48− },
49− {
50− "description": "validation of e-mail addresses",
51− "schema": {"format": "email"},
52− "tests": [
53− {
54− "description": "a valid e-mail address",
55− "data": "joe.bloggs@example.com",
56− "valid": true
57− },
58− {
59− "description": "an invalid e-mail address",
60− "data": "2962",
61− "valid": false
62− }
63− ]
64− },
65− {
66− "description": "validation of IP addresses",
67− "schema": {"format": "ipv4"},
68− "tests": [
69− {
70− "description": "a valid IP address",
71− "data": "192.168.0.1",
72− "valid": true
73− },
74− {
75− "description": "an IP address with too many components",
76− "data": "127.0.0.0.1",
77− "valid": false
78− },
79− {
80− "description": "an IP address with out-of-range values",
81− "data": "256.256.256.256",
82− "valid": false
83− },
84− {
85− "description": "an IP address without 4 components",
86− "data": "127.0",
87− "valid": false
88− },
89− {
90− "description": "an IP address as an integer",
91− "data": "0x7f000001",
92− "valid": false
93− }
94− ]
95− },
96− {
97− "description": "validation of IPv6 addresses",
98− "schema": {"format": "ipv6"},
99− "tests": [
100− {
101− "description": "a valid IPv6 address",
102− "data": "::1",
103− "valid": true
104− },
105− {
106− "description": "an IPv6 address with out-of-range values",
107− "data": "12345::",
108− "valid": false
109− },
110− {
111− "description": "an IPv6 address with too many components",
112− "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1",
113− "valid": false
114− },
115− {
116− "description": "an IPv6 address containing illegal characters",
117− "data": "::laptop",
118− "valid": false
119− }
120− ]
121− },
122− {
123− "description": "validation of host names",
124− "schema": {"format": "hostname"},
125− "tests": [
126− {
127− "description": "a valid host name",
128− "data": "www.example.com",
129− "valid": true
130− },
131− {
132− "description": "a host name starting with an illegal character",
133− "data": "-a-host-name-that-starts-with--",
134− "valid": false
135− },
136− {
137− "description": "a host name containing illegal characters",
138− "data": "not_a_valid_host_name",
139− "valid": false
140− },
141− {
142− "description": "a host name with a component too long",
143− "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component",
144− "valid": false
145− }
146− ]
147− }
148−]
JSON-Schema-Test-Suite/tests/draft6/optional/zeroTerminatedFloats.jsondeleted−15
@@ -1,15 +0,0 @@
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": true
12− }
13− ]
14− }
15−]
JSON-Schema-Test-Suite/tests/draft6/pattern.jsondeleted−34
@@ -1,34 +0,0 @@
1−[
2− {
3− "description": "pattern validation",
4− "schema": {"pattern": "^a*$"},
5− "tests": [
6− {
7− "description": "a matching pattern is valid",
8− "data": "aaa",
9− "valid": true
10− },
11− {
12− "description": "a non-matching pattern is invalid",
13− "data": "abc",
14− "valid": false
15− },
16− {
17− "description": "ignores non-strings",
18− "data": true,
19− "valid": true
20− }
21− ]
22− },
23− {
24− "description": "pattern is not anchored",
25− "schema": {"pattern": "a+"},
26− "tests": [
27− {
28− "description": "matches a substring",
29− "data": "xxaayy",
30− "valid": true
31− }
32− ]
33− }
34−]
JSON-Schema-Test-Suite/tests/draft6/patternProperties.jsondeleted−141
@@ -1,141 +0,0 @@
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− "description": "patternProperties with boolean schemas",
112− "schema": {
113− "patternProperties": {
114− "f.*": true,
115− "b.*": false
116− }
117− },
118− "tests": [
119− {
120− "description": "object with property matching schema true is valid",
121− "data": {"foo": 1},
122− "valid": true
123− },
124− {
125− "description": "object with property matching schema false is invalid",
126− "data": {"bar": 2},
127− "valid": false
128− },
129− {
130− "description": "object with both properties is invalid",
131− "data": {"foo": 1, "bar": 2},
132− "valid": false
133− },
134− {
135− "description": "empty object is valid",
136− "data": {},
137− "valid": true
138− }
139− ]
140− }
141−]
JSON-Schema-Test-Suite/tests/draft6/properties.jsondeleted−123
@@ -1,123 +0,0 @@
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− "description": "properties with boolean schema",
94− "schema": {
95− "properties": {
96− "foo": true,
97− "bar": false
98− }
99− },
100− "tests": [
101− {
102− "description": "no property present is valid",
103− "data": {},
104− "valid": true
105− },
106− {
107− "description": "only 'true' property present is valid",
108− "data": {"foo": 1},
109− "valid": true
110− },
111− {
112− "description": "only 'false' property present is invalid",
113− "data": {"bar": 2},
114− "valid": false
115− },
116− {
117− "description": "both properties present is invalid",
118− "data": {"foo": 1, "bar": 2},
119− "valid": false
120− }
121− ]
122− }
123−]
JSON-Schema-Test-Suite/tests/draft6/propertyNames.jsondeleted−68
@@ -1,68 +0,0 @@
1−[
2− {
3− "description": "propertyNames validation",
4− "schema": {
5− "propertyNames": {"maxLength": 3}
6− },
7− "tests": [
8− {
9− "description": "all property names valid",
10− "data": {
11− "f": {},
12− "foo": {}
13− },
14− "valid": true
15− },
16− {
17− "description": "some property names invalid",
18− "data": {
19− "foo": {},
20− "foobar": {}
21− },
22− "valid": false
23− },
24− {
25− "description": "object without properties is valid",
26− "data": {},
27− "valid": true
28− },
29− {
30− "description": "non-object is valid",
31− "data": [],
32− "valid": true
33− }
34− ]
35− },
36− {
37− "description": "propertyNames with boolean schema true",
38− "schema": {"propertyNames": true},
39− "tests": [
40− {
41− "description": "object with any properties is valid",
42− "data": {"foo": 1},
43− "valid": true
44− },
45− {
46− "description": "empty object is valid",
47− "data": {},
48− "valid": true
49− }
50− ]
51− },
52− {
53− "description": "propertyNames with boolean schema false",
54− "schema": {"propertyNames": false},
55− "tests": [
56− {
57− "description": "object with any properties is invalid",
58− "data": {"foo": 1},
59− "valid": false
60− },
61− {
62− "description": "empty object is valid",
63− "data": {},
64− "valid": true
65− }
66− ]
67− }
68−]
JSON-Schema-Test-Suite/tests/draft6/ref.jsondeleted−332
@@ -1,332 +0,0 @@
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 invalid",
90− "data": {"slash": "aoeu"},
91− "valid": false
92− },
93− {
94− "description": "tilda invalid",
95− "data": {"tilda": "aoeu"},
96− "valid": false
97− },
98− {
99− "description": "percent invalid",
100− "data": {"percent": "aoeu"},
101− "valid": false
102− },
103− {
104− "description": "slash valid",
105− "data": {"slash": 123},
106− "valid": true
107− },
108− {
109− "description": "tilda valid",
110− "data": {"tilda": 123},
111− "valid": true
112− },
113− {
114− "description": "percent valid",
115− "data": {"percent": 123},
116− "valid": true
117− }
118− ]
119− },
120− {
121− "description": "nested refs",
122− "schema": {
123− "definitions": {
124− "a": {"type": "integer"},
125− "b": {"$ref": "#/definitions/a"},
126− "c": {"$ref": "#/definitions/b"}
127− },
128− "$ref": "#/definitions/c"
129− },
130− "tests": [
131− {
132− "description": "nested ref valid",
133− "data": 5,
134− "valid": true
135− },
136− {
137− "description": "nested ref invalid",
138− "data": "a",
139− "valid": false
140− }
141− ]
142− },
143− {
144− "description": "ref overrides any sibling keywords",
145− "schema": {
146− "definitions": {
147− "reffed": {
148− "type": "array"
149− }
150− },
151− "properties": {
152− "foo": {
153− "$ref": "#/definitions/reffed",
154− "maxItems": 2
155− }
156− }
157− },
158− "tests": [
159− {
160− "description": "ref valid",
161− "data": { "foo": [] },
162− "valid": true
163− },
164− {
165− "description": "ref valid, maxItems ignored",
166− "data": { "foo": [ 1, 2, 3] },
167− "valid": true
168− },
169− {
170− "description": "ref invalid",
171− "data": { "foo": "string" },
172− "valid": false
173− }
174− ]
175− },
176− {
177− "description": "remote ref, containing refs itself",
178− "schema": {"$ref": "http://json-schema.org/draft-04/schema#"},
179− "tests": [
180− {
181− "description": "remote ref valid",
182− "data": {"minLength": 1},
183− "valid": true
184− },
185− {
186− "description": "remote ref invalid",
187− "data": {"minLength": -1},
188− "valid": false
189− }
190− ]
191− },
192− {
193− "description": "property named $ref that is not a reference",
194− "schema": {
195− "properties": {
196− "$ref": {"type": "string"}
197− }
198− },
199− "tests": [
200− {
201− "description": "property named $ref valid",
202− "data": {"$ref": "a"},
203− "valid": true
204− },
205− {
206− "description": "property named $ref invalid",
207− "data": {"$ref": 2},
208− "valid": false
209− }
210− ]
211− },
212− {
213− "description": "$ref to boolean schema true",
214− "schema": {
215− "$ref": "#/definitions/bool",
216− "definitions": {
217− "bool": true
218− }
219− },
220− "tests": [
221− {
222− "description": "any value is valid",
223− "data": "foo",
224− "valid": true
225− }
226− ]
227− },
228− {
229− "description": "$ref to boolean schema false",
230− "schema": {
231− "$ref": "#/definitions/bool",
232− "definitions": {
233− "bool": false
234− }
235− },
236− "tests": [
237− {
238− "description": "any value is invalid",
239− "data": "foo",
240− "valid": false
241− }
242− ]
243− },
244− {
245− "description": "Recursive references between schemas",
246− "schema": {
247− "$id": "http://localhost:1234/tree",
248− "description": "tree of nodes",
249− "type": "object",
250− "properties": {
251− "meta": {"type": "string"},
252− "nodes": {
253− "type": "array",
254− "items": {"$ref": "node"}
255− }
256− },
257− "required": ["meta", "nodes"],
258− "definitions": {
259− "node": {
260− "$id": "http://localhost:1234/node",
261− "description": "node",
262− "type": "object",
263− "properties": {
264− "value": {"type": "number"},
265− "subtree": {"$ref": "tree"}
266− },
267− "required": ["value"]
268− }
269− }
270− },
271− "tests": [
272− {
273− "description": "valid tree",
274− "data": {
275− "meta": "root",
276− "nodes": [
277− {
278− "value": 1,
279− "subtree": {
280− "meta": "child",
281− "nodes": [
282− {"value": 1.1},
283− {"value": 1.2}
284− ]
285− }
286− },
287− {
288− "value": 2,
289− "subtree": {
290− "meta": "child",
291− "nodes": [
292− {"value": 2.1},
293− {"value": 2.2}
294− ]
295− }
296− }
297− ]
298− },
299− "valid": true
300− },
301− {
302− "description": "invalid tree",
303− "data": {
304− "meta": "root",
305− "nodes": [
306− {
307− "value": 1,
308− "subtree": {
309− "meta": "child",
310− "nodes": [
311− {"value": "string is invalid"},
312− {"value": 1.2}
313− ]
314− }
315− },
316− {
317− "value": 2,
318− "subtree": {
319− "meta": "child",
320− "nodes": [
321− {"value": 2.1},
322− {"value": 2.2}
323− ]
324− }
325− }
326− ]
327− },
328− "valid": false
329− }
330− ]
331− }
332−]
JSON-Schema-Test-Suite/tests/draft6/refRemote.jsondeleted−171
@@ -1,171 +0,0 @@
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": "base URI change",
54− "schema": {
55− "$id": "http://localhost:1234/",
56− "items": {
57− "$id": "folder/",
58− "items": {"$ref": "folderInteger.json"}
59− }
60− },
61− "tests": [
62− {
63− "description": "base URI change ref valid",
64− "data": [[1]],
65− "valid": true
66− },
67− {
68− "description": "base URI change ref invalid",
69− "data": [["a"]],
70− "valid": false
71− }
72− ]
73− },
74− {
75− "description": "base URI change - change folder",
76− "schema": {
77− "$id": "http://localhost:1234/scope_change_defs1.json",
78− "type" : "object",
79− "properties": {
80− "list": {"$ref": "#/definitions/baz"}
81− },
82− "definitions": {
83− "baz": {
84− "$id": "folder/",
85− "type": "array",
86− "items": {"$ref": "folderInteger.json"}
87− }
88− }
89− },
90− "tests": [
91− {
92− "description": "number is valid",
93− "data": {"list": [1]},
94− "valid": true
95− },
96− {
97− "description": "string is invalid",
98− "data": {"list": ["a"]},
99− "valid": false
100− }
101− ]
102− },
103− {
104− "description": "base URI change - change folder in subschema",
105− "schema": {
106− "$id": "http://localhost:1234/scope_change_defs2.json",
107− "type" : "object",
108− "properties": {
109− "list": {"$ref": "#/definitions/baz/definitions/bar"}
110− },
111− "definitions": {
112− "baz": {
113− "$id": "folder/",
114− "definitions": {
115− "bar": {
116− "type": "array",
117− "items": {"$ref": "folderInteger.json"}
118− }
119− }
120− }
121− }
122− },
123− "tests": [
124− {
125− "description": "number is valid",
126− "data": {"list": [1]},
127− "valid": true
128− },
129− {
130− "description": "string is invalid",
131− "data": {"list": ["a"]},
132− "valid": false
133− }
134− ]
135− },
136− {
137− "description": "root ref in remote ref",
138− "schema": {
139− "$id": "http://localhost:1234/object",
140− "type": "object",
141− "properties": {
142− "name": {"$ref": "name.json#/definitions/orNull"}
143− }
144− },
145− "tests": [
146− {
147− "description": "string is valid",
148− "data": {
149− "name": "foo"
150− },
151− "valid": true
152− },
153− {
154− "description": "null is valid",
155− "data": {
156− "name": null
157− },
158− "valid": true
159− },
160− {
161− "description": "object is invalid",
162− "data": {
163− "name": {
164− "name": null
165− }
166− },
167− "valid": false
168− }
169− ]
170− }
171−]
JSON-Schema-Test-Suite/tests/draft6/required.jsondeleted−60
@@ -1,60 +0,0 @@
1−[
2− {
3− "description": "required validation",
4− "schema": {
5− "properties": {
6− "foo": {},
7− "bar": {}
8− },
9− "required": ["foo"]
10− },
11− "tests": [
12− {
13− "description": "present required property is valid",
14− "data": {"foo": 1},
15− "valid": true
16− },
17− {
18− "description": "non-present required property is invalid",
19− "data": {"bar": 1},
20− "valid": false
21− },
22− {
23− "description": "ignores non-objects",
24− "data": 12,
25− "valid": true
26− }
27− ]
28− },
29− {
30− "description": "required default validation",
31− "schema": {
32− "properties": {
33− "foo": {}
34− }
35− },
36− "tests": [
37− {
38− "description": "not required by default",
39− "data": {},
40− "valid": true
41− }
42− ]
43− },
44− {
45− "description": "required with empty array",
46− "schema": {
47− "properties": {
48− "foo": {}
49− },
50− "required": []
51− },
52− "tests": [
53− {
54− "description": "property not required",
55− "data": {},
56− "valid": true
57− }
58− ]
59− }
60−]
JSON-Schema-Test-Suite/tests/draft6/type.jsondeleted−345
@@ -1,345 +0,0 @@
1−[
2− {
3− "description": "integer type matches integers",
4− "schema": {"type": "integer"},
5− "tests": [
6− {
7− "description": "an integer is an integer",
8− "data": 1,
9− "valid": true
10− },
11− {
12− "description": "a float is not an integer",
13− "data": 1.1,
14− "valid": false
15− },
16− {
17− "description": "a string is not an integer",
18− "data": "foo",
19− "valid": false
20− },
21− {
22− "description": "a string is still not an integer, even if it looks like one",
23− "data": "1",
24− "valid": false
25− },
26− {
27− "description": "an object is not an integer",
28− "data": {},
29− "valid": false
30− },
31− {
32− "description": "an array is not an integer",
33− "data": [],
34− "valid": false
35− },
36− {
37− "description": "a boolean is not an integer",
38− "data": true,
39− "valid": false
40− },
41− {
42− "description": "null is not an integer",
43− "data": null,
44− "valid": false
45− }
46− ]
47− },
48− {
49− "description": "number type matches numbers",
50− "schema": {"type": "number"},
51− "tests": [
52− {
53− "description": "an integer is a number",
54− "data": 1,
55− "valid": true
56− },
57− {
58− "description": "a float is a number",
59− "data": 1.1,
60− "valid": true
61− },
62− {
63− "description": "a string is not a number",
64− "data": "foo",
65− "valid": false
66− },
67− {
68− "description": "a string is still not a number, even if it looks like one",
69− "data": "1",
70− "valid": false
71− },
72− {
73− "description": "an object is not a number",
74− "data": {},
75− "valid": false
76− },
77− {
78− "description": "an array is not a number",
79− "data": [],
80− "valid": false
81− },
82− {
83− "description": "a boolean is not a number",
84− "data": true,
85− "valid": false
86− },
87− {
88− "description": "null is not a number",
89− "data": null,
90− "valid": false
91− }
92− ]
93− },
94− {
95− "description": "string type matches strings",
96− "schema": {"type": "string"},
97− "tests": [
98− {
99− "description": "1 is not a string",
100− "data": 1,
101− "valid": false
102− },
103− {
104− "description": "a float is not a string",
105− "data": 1.1,
106− "valid": false
107− },
108− {
109− "description": "a string is a string",
110− "data": "foo",
111− "valid": true
112− },
113− {
114− "description": "a string is still a string, even if it looks like a number",
115− "data": "1",
116− "valid": true
117− },
118− {
119− "description": "an object is not a string",
120− "data": {},
121− "valid": false
122− },
123− {
124− "description": "an array is not a string",
125− "data": [],
126− "valid": false
127− },
128− {
129− "description": "a boolean is not a string",
130− "data": true,
131− "valid": false
132− },
133− {
134− "description": "null is not a string",
135− "data": null,
136− "valid": false
137− }
138− ]
139− },
140− {
141− "description": "object type matches objects",
142− "schema": {"type": "object"},
143− "tests": [
144− {
145− "description": "an integer is not an object",
146− "data": 1,
147− "valid": false
148− },
149− {
150− "description": "a float is not an object",
151− "data": 1.1,
152− "valid": false
153− },
154− {
155− "description": "a string is not an object",
156− "data": "foo",
157− "valid": false
158− },
159− {
160− "description": "an object is an object",
161− "data": {},
162− "valid": true
163− },
164− {
165− "description": "an array is not an object",
166− "data": [],
167− "valid": false
168− },
169− {
170− "description": "a boolean is not an object",
171− "data": true,
172− "valid": false
173− },
174− {
175− "description": "null is not an object",
176− "data": null,
177− "valid": false
178− }
179− ]
180− },
181− {
182− "description": "array type matches arrays",
183− "schema": {"type": "array"},
184− "tests": [
185− {
186− "description": "an integer is not an array",
187− "data": 1,
188− "valid": false
189− },
190− {
191− "description": "a float is not an array",
192− "data": 1.1,
193− "valid": false
194− },
195− {
196− "description": "a string is not an array",
197− "data": "foo",
198− "valid": false
199− },
200− {
201− "description": "an object is not an array",
202− "data": {},
203− "valid": false
204− },
205− {
206− "description": "an array is an array",
207− "data": [],
208− "valid": true
209− },
210− {
211− "description": "a boolean is not an array",
212− "data": true,
213− "valid": false
214− },
215− {
216− "description": "null is not an array",
217− "data": null,
218− "valid": false
219− }
220− ]
221− },
222− {
223− "description": "boolean type matches booleans",
224− "schema": {"type": "boolean"},
225− "tests": [
226− {
227− "description": "an integer is not a boolean",
228− "data": 1,
229− "valid": false
230− },
231− {
232− "description": "a float is not a boolean",
233− "data": 1.1,
234− "valid": false
235− },
236− {
237− "description": "a string is not a boolean",
238− "data": "foo",
239− "valid": false
240− },
241− {
242− "description": "an object is not a boolean",
243− "data": {},
244− "valid": false
245− },
246− {
247− "description": "an array is not a boolean",
248− "data": [],
249− "valid": false
250− },
251− {
252− "description": "a boolean is a boolean",
253− "data": true,
254− "valid": true
255− },
256− {
257− "description": "null is not a boolean",
258− "data": null,
259− "valid": false
260− }
261− ]
262− },
263− {
264− "description": "null type matches only the null object",
265− "schema": {"type": "null"},
266− "tests": [
267− {
268− "description": "an integer is not null",
269− "data": 1,
270− "valid": false
271− },
272− {
273− "description": "a float is not null",
274− "data": 1.1,
275− "valid": false
276− },
277− {
278− "description": "a string is not null",
279− "data": "foo",
280− "valid": false
281− },
282− {
283− "description": "an object is not null",
284− "data": {},
285− "valid": false
286− },
287− {
288− "description": "an array is not null",
289− "data": [],
290− "valid": false
291− },
292− {
293− "description": "a boolean is not null",
294− "data": true,
295− "valid": false
296− },
297− {
298− "description": "null is null",
299− "data": null,
300− "valid": true
301− }
302− ]
303− },
304− {
305− "description": "multiple types can be specified in an array",
306− "schema": {"type": ["integer", "string"]},
307− "tests": [
308− {
309− "description": "an integer is valid",
310− "data": 1,
311− "valid": true
312− },
313− {
314− "description": "a string is valid",
315− "data": "foo",
316− "valid": true
317− },
318− {
319− "description": "a float is invalid",
320− "data": 1.1,
321− "valid": false
322− },
323− {
324− "description": "an object is invalid",
325− "data": {},
326− "valid": false
327− },
328− {
329− "description": "an array is invalid",
330− "data": [],
331− "valid": false
332− },
333− {
334− "description": "a boolean is invalid",
335− "data": true,
336− "valid": false
337− },
338− {
339− "description": "null is invalid",
340− "data": null,
341− "valid": false
342− }
343− ]
344− }
345−]
JSON-Schema-Test-Suite/tests/draft6/uniqueItems.jsondeleted−79
@@ -1,79 +0,0 @@
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−]
JSON-Schema-Test-Suite/tox.inideleted−8
@@ -1,8 +0,0 @@
1−[tox]
2−minversion = 1.6
3−envlist = py27
4−skipsdist = True
5−
6−[testenv]
7−deps = jsonschema
8−commands = {envpython} bin/jsonschema_suite check
README.md+45−13
@@ -1,25 +1,57 @@
1−# DEPRECATION NOTICE
1+![hjsonschema logo](./logo.jpg)
22
3−`hjsonschema` was an attempt to build a very modular JSON Schema library. Validators have [a concrete type](src/JSONSchema/Validator/Types.hs) and can be mixed and matched into new [Specs](src/JSONSchema/Types.hs).
3+A Haskell implementation of the current [JSON Schema](http://json-schema.org/) specification (Draft 4).
44
5−However this flexibility came at the price of complicating the code. I don't think it was the right tradeoff, especially since situations where you'd want to change what validators make up a `Spec` at runtime seem rare.
5+[Hackage](https://hackage.haskell.org/package/hjsonschema) / [GitHub](https://github.com/seagreen/hjsonschema) / [Travis CI](https://travis-ci.org/seagreen/hjsonschema)
66
7−Also, there are many parts of JSON Schema that `hjsonschema` doesn't implement properly (as you can see from the issue tracker). I'm hoping that a new JSON Schema library will come along that handles these correctly. In the meantime I'm happy to merge working fixes into here.
7+NOTE: You CANNOT use untrusted JSON data to make schemas. Schemas with circular references can cause infinite loops. See the issue list for more info.
88
9−# Links
9+# Example
1010
11−[Hackage](https://hackage.haskell.org/package/hjsonschema) / [GitHub](https://github.com/seagreen/hjsonschema) / [Travis CI](https://travis-ci.org/seagreen/hjsonschema)
11+See [here](https://github.com/seagreen/hjsonschema/blob/master/examples/Standard.hs).
1212
13−# Example
13+# Tests
14+
15+## Install
16+
17+`git submodule update --init`
18+
19+## Run
20+
21+Will run self-contained:
22+
23+`cabal test local`
24+
25+Will start an HTTP server temporarily on port 1234:
26+
27+`cabal test remote`
28+
29+# Details
30+
31+## Goals
32+
33++ Be a correct and fast implementation of the spec.
34+
35++ Be a useful reference for implementers in other languages. Haskell's high level nature, expressive type system and referential transparency suit this purpose well.
36+
37+## Good Parts
38+
39++ Passes all the tests in the [language agnostic test suite](https://github.com/json-schema/JSON-Schema-Test-Suite).
40+
41++ Very modular, which should make it easy to support future versions of the specification.
42+
43+## Bad Parts
44+
45++ Uses the [pcre-heavy](https://hackage.haskell.org/package/pcre-heavy) regular expression library for the "pattern" validator. It should use a library based on the ECMA 262 regex dialect, which the [spec](http://json-schema.org/latest/json-schema-validation.html#anchor33) requires.
1446
15−See [here](https://github.com/seagreen/hjsonschema/blob/master/examples/Simple.hs).
47+## Notes
1648
17−# System dependencies
49++ `src/draft4.json` is from commit # cc8ec81ce0abe2385ebd6c2a6f2d6deb646f874a [here](https://github.com/json-schema/json-schema).
1850
19−+ Requires [pcre](http://www.pcre.org/) (`pkgs.pcre` in Nixpkgs).
51+## Credits
2052
21−## Vendoring
53+[TJ Weigel](http://tjweigel.com/) created the logo.
2254
23−+ `JSON-Schema-Test-Suite` is vendored from commit # c1b12bf699f29a04b4286711c6e3bbfba66f21e5 [here](https://github.com/json-schema-org/JSON-Schema-Test-Suite).
55+[Tim Baumann](https://github.com/timjb) wrote [aeson-schema](https://hackage.haskell.org/package/aeson-schema), on which hjsonschema's test code and its implementation of `SchemaGraph` were based.
2456
25−+ `src/draft4.json` is from commit # c1b12bf699f29a04b4286711c6e3bbfba66f21e5 [here](https://github.com/json-schema/json-schema). The [root ref in remote ref](./JSON-Schema-Test-Suite/tests/draft4/refRemote.json) test has been modified to fix [#175](https://github.com/json-schema-org/JSON-Schema-Test-Suite/issues/175).
57+[Julian Berman](https://github.com/Julian) maintains the fantastic [language agnostic test suite](https://github.com/json-schema/JSON-Schema-Test-Suite).
changelog.mddeleted−209
@@ -1,209 +0,0 @@
1−# 1.8.0
2−
3−+ Add GHC 8.4 support (thanks @4e6 !).
4−+ Drop GHC 7.10 support.
5−+ Fix JSON Pointer resolution error.
6−
7−# 1.8.0
8−
9−+ Allow HTTPS references (thanks @creichert!).
10−+ Use `safe-exceptions` to eliminate the risk of catching asynchronous exceptions.
11−
12−# 1.7.2
13−
14−+ Remove upper bounds.
15−
16−# 1.7.1
17−
18−+ Bump http-types.
19−
20−# 1.7.0
21−
22−+ Test with GHC 8.2. Drop GHC 7.8.
23−+ Rework `allUniqueValues` related utility functions.
24−
25−# 1.6.3
26−
27−+ Bump hjsonpointer and QuickCheck.
28−
29−# 1.6.2
30−
31−+ Bump aeson.
32−
33−# 1.6.1
34−
35−+ Fix Haddocks.
36−
37−# 1.6.0
38−
39−+ Fix defect where validators alongside "$ref" weren't ignored.
40−
41−+ Fix defect where local references would fail if an "id" key had set resolution scope to start from a different document.
42−
43−+ Vendor latest tests.
44−
45−+ Remove `ReferencedSchemas`.
46−
47−+ Create `Scope` to hold information that changes during validation.
48−
49−+ Use a sum type for "type" values. Thanks to Philip Weaver (GitHub @pheaver).
50−
51−# 1.5.0.1
52−
53−+ Raise test dep upper bounds.
54−
55−# 1.5.0.0
56−
57−+ Report details of `"required"` validator failure.
58−+ Bump `directory`.
59−
60−# 1.4.0.0
61−
62−+ Rename `Data.JsonSchema.*` modules to `JSONSchema.*`.
63−+ Rename `Data.Validator.*` modules to `JSONSchema.Validator.*`.
64−
65−# 1.3.0.1
66−
67−+ Bump `vector`.
68−
69−# 1.3.0.0
70−
71−+ Rewrite failure messages.
72−
73−We used to return a list of every failed validator, no matter how far it was buried within subschemas of the original schema.
74−
75−Now we return a tree of failure messages, so that if the first schema had only three validators, then no more than three top level failures will be returned.
76−
77−+ Move the code to parse each validator from JSON from `Data.Validator.Draft4` into the validators' modules themselves.
78−
79−+ Switch from Prelude to Protolude.
80−
81−+ Switch `Data.JsonSchema.Fetch` from lazy to strict bytestrings.
82−
83−# 1.2.0.2
84−
85−+ Bump hspec.
86−
87−# 1.2.0.1
88−
89−+ Switch to hspec for tests.
90−
91−# 1.2.0.0
92−
93−+ Return `AdditionalPropertiesObject` error correctly (was mistakenly returning `AdditionalItemsObject` instead.
94−+ Don't silence errors resulting from subschemas of "anyOf" or "oneOf".
95−
96−# 1.1.0.1
97−
98−+ Bump `aeson` and `hjsonpointer`.
99−
100−# 1.1.0.0
101−
102−+ Rename `schemaForSchemas` to `metaSchema` and `schemaForSchemasBytes` to `metaSchemaBytes`.
103−
104−# 1.0.0.0
105−
106−## Bug fixes:
107−
108−+ Fix JSON Pointer bug. Pointers were being built in reverse order and so were totally invalid.
109−+ Use `.:!` instead of `.:?` to parse the draft 4 schema. The only way to omit optional fields in JSON Schema Draft 4 is to omit them entirely, `"null"` can't be used for this.
110−
111−## API Changes:
112−
113−+ Add referenced schema loop detection.
114−+ Add a new `referencesValidity` function.
115−+ `checkSchema` now checks referenced schema's validity in addition to the starting schema's validity. This change bubbles up to the one-step validation functions as well.
116−+ Switch most of the fetching code to use `URISchemaMap` instead of `ReferencedSchemas`. It didn't need to know about the more complicated data type.
117−+ Rething failure related names. Change `Invalid` to `Failure`, add a new `Invalid` type alias which is only used for final results.
118−+ Failures now include the failing part of the data as well as a JSON Pointer to it, so you don't have to worry about resolving the pointer.
119−
120−## Fundamental Changes:
121−
122−+ Make `Fail` (previously `Failure`) an instance of `Functor`.
123−+ Add a `Validator` data type which is an instance of `Profunctor`.
124−+ Add a `Spec` data type for collections of `Validators`.
125−
126−## General:
127−
128−+ Switch from 2 to 4 space indentation.
129−+ Update the vendored JSON Schema Test Suite.
130−
131−# 0.10.0.3
132−
133−+ Bump http-client.
134−
135−# 0.10.0.2
136−
137−+ Enable GHC 8.
138−
139−# 0.10.0.1
140−
141−+ Fix .cabal file.
142−
143−# 0.10
144−
145−+ Rewrite fetching internals.
146−+ Fix reference resolution defects, add more tests.
147−+ Switch to a Perl style regex library, which is closer to ECMAScript regexes than the previous Posix style one.
148−+ Add one-step validation functions ('fetchFilesystemAndValidate' and 'fetchHTTPAndValidate').
149−+ Alias the validation failure type exported by 'Data.JsonSchema.Draft4' to
150−'Invalid', change its field names.
151−
152−# 0.9
153−
154−+ Partial rewrite. The API of the library has changed, see the examples
155−folder for how to use the new one.
156−
157−+ Users of the library can now write schemas in Haskell as well as JSON.
158−
159−# 0.8
160−
161−+ Improve scope updating and resolving.
162−+ Rename RawSchema's _rsObject field to _rsData.
163−+ Make RawSchema's _rsURI field a Maybe. This way schemas without a starting URI can say so explicitly with Nothing instead of with "".
164−+ Rename Graph to SchemaGraph. Declare it with data instead of type. Give it a field referencing the starting schema. This field is used to find the curent schema if no URI is in scope and a self-referencing $ref is found (e.g. "#").
165−+ Change the order of the last two arguments to fetchReferencedSchemas.
166−
167−# 0.7.1
168−
169−+ Support GHC 7.8 again.
170−
171−# 0.7
172−
173−Change error type from Text to ValidationFailure.
174−
175−Revert the 0.6 changes to validate. Also switch from Vector to list. Validate is now:
176− Schema err -> Value -> [ValidationFailure err]
177−
178−Add fetchReferencedSchemas', which lets the user provide their own MonadIO function to be used when fetching schemas. This lets them do things like only fetch schemas from particular domains.
179−
180−# 0.6
181−
182−Break the API so the library doesn't induce boolean blindness.
183−
184−Change validate
185− was: Schema -> Value -> Vector ValErr
186− now: Schema -> Value -> Either (Vector ValErr) Value
187−
188−Change Schema
189− was: type Schema = Vector Validator
190− now: newtype Schema = Schema { _unSchema :: [Validator] }
191−
192−# 0.5.3
193−
194−+ Switch from http-conduit to http-client.
195−
196−# 0.5.2
197−
198−+ Add convenience function for validating and compiling draft 4 schemas simultaneously.
199−
200−# 0.5.1
201−
202−+ Switch from wreq to http-conduit; drop lens dependency.
203−
204−# 0.5
205−
206−+ Start changelog.
207−+ Rename Utils.hs to Helpers.hs.
208−+ Move all non-ValidatorGen functions in Validators.hs to Helpers.hs.
209−+ Various touchups.
changelog.txtnew file+65
@@ -0,0 +1,65 @@
1+# 0.9
2+
3++ Partial rewrite. The API of the library has changed, see the examples
4+folder for how to use the new one.
5+
6++ Users of the library can now write schemas in Haskell as well as JSON.
7+
8+# 0.8
9+
10++ Improve scope updating and resolving.
11++ Rename RawSchema's _rsObject field to _rsData.
12++ Make RawSchema's _rsURI field a Maybe. This way schemas without a starting
13+URI can say so explicitly with Nothing instead of with "".
14++ Rename Graph to SchemaGraph. Declare it with data instead of type. Give it a
15+field referencing the starting schema. This field is used to find the curent
16+schema if no URI is in scope and a self-referencing $ref is found (e.g. "#").
17++ Change the order of the last two arguments to fetchReferencedSchemas.
18+
19+# 0.7.1
20+
21++ Support GHC 7.8 again.
22+
23+# 0.7
24+
25+Change error type from Text to ValidationFailure.
26+
27+Revert the 0.6 changes to validate. Also switch from Vector
28+to list. Validate is now:
29+ Schema err -> Value -> [ValidationFailure err]
30+
31+Add fetchReferencedSchemas', which lets the user provide their
32+own MonadIO function to be used when fetching schemas. This lets
33+them do things like only fetch schemas from particular domains.
34+
35+# 0.6
36+
37+Break the API so the library doesn't induce boolean blindness.
38+
39+Change validate
40+ was: Schema -> Value -> Vector ValErr
41+ now: Schema -> Value -> Either (Vector ValErr) Value
42+
43+Change Schema
44+ was: type Schema = Vector Validator
45+ now: newtype Schema = Schema { _unSchema :: [Validator] }
46+
47+# 0.5.3
48+
49++ Switch from http-conduit to http-client.
50+
51+# 0.5.2
52+
53++ Add convenience function for validating and compiling draft 4 schemas
54+simultaneously.
55+
56+# 0.5.1
57+
58++ Switch from wreq to http-conduit; drop lens dependency.
59+
60+# 0.5
61+
62++ Start changelog.
63++ Rename Utils.hs to Helpers.hs.
64++ Move all non-ValidatorGen functions in Validators.hs to Helpers.hs.
65++ Various touchups.
examples/AlternateSchema.hsdeleted−200
@@ -1,200 +0,0 @@
1−-- | An implementation of JSON Schema Draft 4 based on 'HashMap Text Value'
2−-- instead of a custom record type like 'JSONSchema.Draft4'.
3−--
4−-- If you're writing code for a new schema specification you probably want
5−-- to copy this module instead of the 'JSONSchema.Draft4'. While it's
6−-- less convenient to write schemas in Haskell without a record type, you
7−-- can get the implementation finished with far fewer lines of code.
8−module AlternateSchema where
9−
10−import Protolude
11−
12−import Data.Aeson (FromJSON(..), Value(..), decodeStrict)
13−import qualified Data.Aeson as AE
14−import qualified Data.HashMap.Strict as HM
15−import Data.Maybe (fromMaybe)
16−import Data.Profunctor (Profunctor(..))
17−
18−import JSONSchema.Draft4 (ValidatorFailure(..), metaSchemaBytes)
19−import JSONSchema.Fetch (SchemaWithURI(..), URISchemaMap(..))
20−import qualified JSONSchema.Fetch as FE
21−import JSONSchema.Types (Schema(..), Spec(..))
22−import qualified JSONSchema.Types as JT
23−import qualified JSONSchema.Validator.Draft4 as D4
24−import JSONSchema.Validator.Reference (BaseURI(..), Scope(..),
25− updateResolutionScope)
26−
27−--------------------------------------------------
28−-- * Basic fetching tools
29−--------------------------------------------------
30−
31−referencesViaHTTP
32− :: SchemaWithURI Schema
33− -> IO (Either FE.HTTPFailure (FE.URISchemaMap Schema))
34−referencesViaHTTP = FE.referencesViaHTTP' draft4FetchInfo
35−
36−draft4FetchInfo :: FE.FetchInfo Schema
37−draft4FetchInfo = FE.FetchInfo embedded (lookup "id") (lookup "$ref")
38− where
39− lookup :: Text -> Schema -> Maybe Text
40− lookup k (Schema s) =
41− case HM.lookup k s of
42− Just (String t) -> Just t
43− _ -> Nothing
44−
45−-- | An implementation of 'JT.embedded'.
46−embedded :: Schema -> ([Schema], [Schema])
47−embedded s =
48− JT.embedded (d4Spec mempty mempty (Scope s Nothing (BaseURI Nothing))) s
49−
50−--------------------------------------------------
51−-- * Main API
52−--------------------------------------------------
53−
54−validate
55− :: URISchemaMap Schema
56− -> SchemaWithURI Schema
57− -> Value
58− -> [ValidatorFailure]
59−validate schemaMap sw =
60− JT.validate (d4Spec schemaMap visited scope) (_swSchema sw)
61− where
62− visited :: D4.VisitedSchemas
63− visited = D4.VisitedSchemas [(Nothing, Nothing)]
64−
65− schemaId :: Maybe Text
66− schemaId = FE._fiId draft4FetchInfo (_swSchema sw)
67−
68− scope :: Scope Schema
69− scope = Scope
70− { _topLevelDocument = _swSchema sw
71− , _documentURI = _swURI sw
72− , _currentBaseURI = updateResolutionScope (BaseURI (_swURI sw))
73− schemaId
74− }
75−
76−-- | A schema for schemas themselves. Uses @src/draft4.json@ which is loaded
77−-- at compile time.
78−metaSchema :: Schema
79−metaSchema =
80− fromMaybe (panic "Schema decode failed (this should never happen)")
81− . decodeStrict
82− $ metaSchemaBytes
83−
84−checkSchema :: Schema -> [ValidatorFailure]
85−checkSchema = validate schemaMap (SchemaWithURI metaSchema Nothing)
86− . Object
87− . _unSchema
88− where
89− schemaMap :: URISchemaMap Schema
90− schemaMap =
91− URISchemaMap (HM.singleton "http://json-schema.org/draft-04/schema"
92− metaSchema)
93−
94−--------------------------------------------------
95−-- * Spec
96−--------------------------------------------------
97−
98−validateSubschema
99− :: URISchemaMap Schema
100− -> D4.VisitedSchemas
101− -> Scope Schema
102− -> Schema
103− -> Value
104− -> [ValidatorFailure]
105−validateSubschema schemaMap visited scope schema =
106− JT.validate (d4Spec schemaMap visited newScope) schema
107− where
108− schemaId :: Maybe Text
109− schemaId = FE._fiId draft4FetchInfo schema
110−
111− newScope :: Scope Schema
112− newScope = scope
113− { _currentBaseURI = updateResolutionScope (_currentBaseURI scope)
114− schemaId
115− }
116−
117−d4Spec
118− :: URISchemaMap Schema
119− -> D4.VisitedSchemas
120− -> Scope Schema
121− -> Spec Schema ValidatorFailure
122− -- ^ Here we reuses 'ValidatorFailure' from
123− -- 'JSONSchema.Draft4.Failure'. If your validators have different
124− -- failure possibilities you'll need to create your own validator
125− -- failure type.
126−d4Spec schemaMap visited scope =
127− Spec $
128− [ dimap
129− f
130− FailureRef
131− (D4.refValidator (FE.getReference schemaMap) updateScope
132− valRef visited scope)
133− ]
134−
135− <> fmap (lmap disableIfRefPresent)
136− [ dimap f FailureMultipleOf D4.multipleOfValidator
137− , dimap f FailureMaximum D4.maximumValidator
138− , dimap f FailureMinimum D4.minimumValidator
139−
140− , dimap f FailureMaxLength D4.maxLengthValidator
141− , dimap f FailureMinLength D4.minLengthValidator
142− , dimap f FailurePattern D4.patternValidator
143−
144− , dimap f FailureMaxItems D4.maxItemsValidator
145− , dimap f FailureMinItems D4.minItemsValidator
146− , dimap f FailureUniqueItems D4.uniqueItemsValidator
147− , dimap
148− (fromMaybe D4.emptyItems . f)
149− (\err -> case err of
150− D4.IRInvalidItems e -> FailureItems e
151− D4.IRInvalidAdditional e -> FailureAdditionalItems e)
152− (D4.itemsRelatedValidator descend)
153− , lmap f D4.definitionsEmbedded
154−
155− , dimap f FailureMaxProperties D4.maxPropertiesValidator
156− , dimap f FailureMinProperties D4.minPropertiesValidator
157− , dimap f FailureRequired D4.requiredValidator
158− , dimap f FailureDependencies (D4.dependenciesValidator descend)
159− , dimap
160− (fromMaybe D4.emptyProperties . f)
161− FailurePropertiesRelated
162− (D4.propertiesRelatedValidator descend)
163−
164− , dimap f FailureEnum D4.enumValidator
165− , dimap f FailureType D4.typeValidator
166− , dimap f FailureAllOf (D4.allOfValidator lateral)
167− , dimap f FailureAnyOf (D4.anyOfValidator lateral)
168− , dimap f FailureOneOf (D4.oneOfValidator lateral)
169− , dimap f FailureNot (D4.notValidator lateral)
170− ]
171− where
172− f :: FromJSON a => Schema -> Maybe a
173− f (Schema a) =
174− case AE.fromJSON (Object a) of
175− AE.Error _ -> Nothing
176− AE.Success b -> Just b
177−
178− disableIfRefPresent :: Schema -> Schema
179− disableIfRefPresent schema =
180− case FE._fiRef draft4FetchInfo schema of
181− Nothing -> schema
182− Just _ -> Schema mempty
183−
184− updateScope :: BaseURI -> Schema -> BaseURI
185− updateScope uri schema =
186− updateResolutionScope uri (FE._fiId draft4FetchInfo schema)
187−
188− valRef
189− :: D4.VisitedSchemas
190− -> Scope Schema
191− -> Schema
192− -> Value
193− -> [ValidatorFailure]
194− valRef vis sc = JT.validate (d4Spec schemaMap vis sc)
195−
196− descend :: Schema -> Value -> [ValidatorFailure]
197− descend = validateSubschema schemaMap mempty scope
198−
199− lateral :: Schema -> Value -> [ValidatorFailure]
200− lateral = validateSubschema schemaMap visited scope
examples/CustomSchema.hsnew file+68
@@ -0,0 +1,68 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+
3+-- | A custom schema made up of one validator from 'Data.Validator.Draft4'
4+-- and one original validator.
5+--
6+-- This is a simple example because it doesn't allow references (so it
7+-- doesn't need to define an 'embed' function @Schema -> [Schema]@ for use
8+-- with 'fetchReferencedSchemas'.
9+
10+module CustomSchema where
11+
12+import Control.Applicative
13+import Data.Aeson
14+import Data.Maybe (maybeToList)
15+import Data.Monoid
16+import Data.Text (Text)
17+import qualified Data.Text as T
18+
19+import qualified Data.Validator.Draft4 as VA
20+import qualified Data.Validator.Failure as FR
21+
22+-- | Our custom validator.
23+oddLength :: Bool -> Text -> Maybe (FR.Failure () )
24+oddLength b t
25+ | b == odd (T.length t) = Nothing
26+ | otherwise = Just (FR.Failure () (Bool b) mempty)
27+
28+data CustomError
29+ = MaxLength
30+ | OddLength
31+
32+-- If we were really using the schema we would also need ToJSON and FromJSON
33+-- instances.
34+data Schema = Schema
35+ { _schemaMaxLength :: Maybe Int
36+ , _schemaOddLength :: Maybe Bool
37+ }
38+
39+-- | Since every 'Schema' is valid we don't need to bother defining something
40+-- like 'Data.JsonSchema.Draft4.checkValidity' for this schema.
41+validate :: Schema -> Value -> [FR.Failure CustomError]
42+validate s (String x) = concat
43+ [ f _schemaMaxLength (FR.setFailure MaxLength) (fmap maybeToList . VA.maxLength)
44+ , f _schemaOddLength (FR.setFailure OddLength) (fmap maybeToList . oddLength)
45+ ]
46+ where
47+ -- This pattern is overkill here, but is helpful if you have lots of
48+ -- validators (e.g. the Draft 4 schema has 27).
49+ f :: (Schema -> Maybe val)
50+ -> (err -> FR.Failure CustomError)
51+ -> (val -> Text -> [err])
52+ -> [FR.Failure CustomError]
53+ f field modifyError runVal =
54+ maybe mempty (\val -> modifyError <$> runVal val x) (field s)
55+validate _ _ = mempty -- Our schema passes everything that isn't a string.
56+
57+example :: IO ()
58+example =
59+ case validate schema badData of
60+ [] -> error "We validated bad data."
61+ [FR.Failure OddLength _ _] -> return () -- Success.
62+ _ -> error "We got a different failure than expected."
63+ where
64+ schema :: Schema
65+ schema = Schema (Just 100) (Just True)
66+
67+ badData :: Value
68+ badData = String "even"
examples/Main.hsnew file+19
@@ -0,0 +1,19 @@
1+
2+module Main where
3+
4+import Test.Tasty (TestTree, defaultMain, testGroup)
5+import qualified Test.Tasty.HUnit as HU
6+
7+import qualified CustomSchema as C
8+import qualified PrettyShowFailure as P
9+import qualified Standard as S
10+
11+main :: IO ()
12+main = defaultMain (testGroup "Check Examples" exampleTests)
13+
14+exampleTests :: [TestTree]
15+exampleTests =
16+ [ HU.testCase "Standard Example" S.example
17+ , HU.testCase "PrettyShowFailure Example" P.example
18+ , HU.testCase "CustomSchema Example" C.example
19+ ]
examples/PrettyShowFailure.hsnew file+58
@@ -0,0 +1,58 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+
3+module PrettyShowFailure where
4+
5+import Data.Aeson
6+import qualified Data.Aeson.Pointer as AP
7+import Data.Monoid
8+
9+import qualified Data.JsonSchema.Draft4 as D4
10+
11+badData :: Value
12+badData = toJSON [1, 2 :: Int]
13+
14+failure :: D4.Failure
15+failure = D4.Failure
16+ { D4._failureValidatorsCalled = D4.Items D4.MultipleOf
17+ , D4._failureFinalValidator = Number 2
18+ , D4._failureOffendingData = AP.Pointer [AP.Token "0"]
19+ }
20+
21+example :: IO ()
22+example =
23+ -- 'D4.Failure's contain the sequence of embedded validators that caused
24+ -- the invalidation, the contents of the final validator in that sequence,
25+ -- and a JSON Pointer to the subset of data that caused validation to fail.
26+ --
27+ -- They don't actually contain that subset of data, since it can be derived
28+ -- from the original data and the JSON Pointer.
29+ --
30+ -- If you want to display the invalid subset of the data here's how you
31+ -- resolve the JSON Pointer (which has the field name
32+ -- 'D4._failureOffendingData') against the original data.
33+ --
34+ -- NOTE: You have to have hjsonpointer in your build-depends.
35+ case AP.resolve (D4._failureOffendingData failure) badData of
36+ Left _ -> error "Couldn't resolve pointer."
37+ Right _ -> return () -- Success. We could feed the 'Right' value into
38+ -- the otherwise unused 'msg' if we wanted to
39+ -- display it.
40+
41+msg :: Value -> String
42+msg subsetOfData = unlines
43+ [ "Invalid data. Here's the sequence of validators that caught it:"
44+ , ""
45+ , " " <> show (D4._failureValidatorsCalled failure)
46+ , ""
47+ , "Here's the contents of the final validator in that sequence:"
48+ , ""
49+ , " " <> show (D4._failureFinalValidator failure)
50+ , ""
51+ , "Here's a JSON Pointer to the invalid part of the data:"
52+ , ""
53+ , " " <> show (D4._failureOffendingData failure)
54+ , ""
55+ , "Here's the invalid part of the data:"
56+ , ""
57+ , " " <> show subsetOfData
58+ ]
examples/Simple.hsdeleted−37
@@ -1,37 +0,0 @@
1−module Simple where
2−
3−import Protolude
4−
5−import Data.Aeson (Value(..), decodeStrict, toJSON)
6−import qualified Data.ByteString as BS
7−import qualified Data.List.NonEmpty as NE
8−import Data.Maybe (fromMaybe)
9−
10−import qualified JSONSchema.Draft4 as D4
11−
12−badData :: Value
13−badData = toJSON [True, True]
14−
15−example :: IO ()
16−example = do
17− bts <- BS.readFile "./examples/json/unique.json"
18− let schema = fromMaybe (panic "Invalid schema JSON.") (decodeStrict bts)
19− schemaWithURI = D4.SchemaWithURI
20− schema
21− Nothing -- This would be the URI of the schema
22− -- if it had one. It's used if the schema
23− -- has relative references to other
24− -- schemas.
25−
26− -- Fetch any referenced schemas over HTTP, check that our original schema
27− -- itself is valid, and validate the data.
28− res <- D4.fetchHTTPAndValidate schemaWithURI badData
29− case res of
30− Right () -> panic "We validated bad data."
31− Left (D4.HVRequest _) -> panic ("Error fetching a referenced schema"
32− <> " (either during IO or parsing).")
33− Left (D4.HVSchema _) -> panic "Our 'schema' itself was invalid."
34− Left (D4.HVData (D4.Invalid _ _ failures)) ->
35− case NE.toList failures of
36− [D4.FailureUniqueItems _] -> pure () -- Success.
37− _ -> panic "We got a different failure than expected."
examples/Standard.hsnew file+49
@@ -0,0 +1,49 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+
3+module Standard where
4+
5+import Data.Aeson
6+import qualified Data.Vector as V
7+
8+import qualified Data.JsonSchema.Draft4 as D4
9+
10+schema :: D4.Schema
11+schema = D4.emptySchema { D4._schemaUniqueItems = Just True }
12+
13+schemaContext :: D4.SchemaWithURI D4.Schema
14+schemaContext = D4.SchemaWithURI
15+ { D4._swSchema = schema
16+ , D4._swURI = Nothing
17+ -- ^ If your schema has relative references to other schemas
18+ -- then you'll need to give its URI here.
19+ }
20+
21+badData :: Value
22+badData = Array (V.fromList ["foo", "foo"])
23+
24+example :: IO ()
25+example = do
26+ -- Since we know our schema doesn't reference any other schemas we could
27+ -- skip this step and use @ReferencedSchemas schema mempty@ instead.
28+ --
29+ -- If we make a mistake and out schema does include references to other
30+ -- schemas then those references will always return 'D4.RefResolution'
31+ -- validation failures.
32+ cache <- makeCache
33+
34+ let validate = case D4.checkSchema cache schemaContext of
35+ Left _ -> error "Not a valid schema."
36+ Right f -> f
37+
38+ case validate badData of
39+ [] -> error "We validated bad data."
40+ [D4.Failure D4.UniqueItems _ _] -> return () -- Success.
41+ _ -> error "We got a different failure than expected."
42+
43+ where
44+ makeCache :: IO (D4.ReferencedSchemas D4.Schema)
45+ makeCache = do
46+ res <- D4.referencesViaHTTP schemaContext
47+ case res of
48+ Left _ -> error "Couldn't fetch referenced schemas."
49+ Right cache -> return cache
examples/TwoStep.hsdeleted−48
@@ -1,48 +0,0 @@
1−-- | Differences from @examples/Simple.hs@:
2−--
3−-- * We demonstrate how to do the validation step without IO by first
4−-- getting the references with 'D4.referencesViaFilesystem'.
5−--
6−-- * This shows how to write the starting schema in Haskell instead
7−-- of parsing it from JSON.
8−--
9−-- * This schema references other schemas. Previously we used
10−-- 'fetchHTTPAndValidate' which fetched references over HTTP (though it
11−-- didn't matter because the last schema didn't actually have any).
12−-- This time we need to get them from the filesystem.
13−module TwoStep where
14−
15−import Protolude
16−
17−import Data.Aeson (Value(..), toJSON)
18−import qualified Data.List.NonEmpty as NE
19−
20−import qualified JSONSchema.Draft4 as D4
21−import qualified JSONSchema.Validator.Draft4 as VAL
22−
23−schema :: D4.Schema
24−schema = D4.emptySchema { D4._schemaRef = Just "./unique.json" }
25−
26−schemaContext :: D4.SchemaWithURI D4.Schema
27−schemaContext = D4.SchemaWithURI
28− { D4._swSchema = schema
29− , D4._swURI = Just "./examples/json/start.json"
30− }
31−
32−badData :: Value
33−badData = toJSON [True, True]
34−
35−example :: IO ()
36−example = do
37− res <- D4.referencesViaFilesystem schemaContext
38− let references = case res of
39− Left _ -> panic "Couldn't fetch referenced schemas."
40− Right a -> a
41− validate = case D4.checkSchema references schemaContext of
42− Left _ -> panic "Not a valid schema."
43− Right f -> f
44− case validate badData of
45− [] -> panic "We validated bad data."
46− [D4.FailureRef (VAL.RefInvalid _ _ (D4.FailureUniqueItems _ NE.:|[])) ] ->
47− pure () -- Success
48− _ -> panic "We got a different failure than expected."
examples/json/start.jsondeleted−3
@@ -1,3 +0,0 @@
1−{
2− "$ref": "./unique.json"
3−}
examples/json/unique.jsondeleted−3
@@ -1,3 +0,0 @@
1−{
2− "uniqueItems": true
3−}
hjsonschema.cabal+124−155
@@ -1,162 +1,131 @@
1−name: hjsonschema
2−version: 1.9.0
3−synopsis: JSON Schema library
4−homepage: https://github.com/seagreen/hjsonschema
5−license: MIT
6−license-file: MIT-LICENSE.txt
7−author: Ian Grant Jeffries
8−maintainer: ian@housejeffries.com
9−category: Data
10−build-type: Simple
11−cabal-version: >=1.10
12−-- Rerun multi-ghc-travis (executable make-travis-yml-2) after changing:
13−Tested-With: GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.1
14−extra-source-files:
15− changelog.md
16− JSON-Schema-Test-Suite/remotes/*.json
17− JSON-Schema-Test-Suite/remotes/folder/*.json
18− JSON-Schema-Test-Suite/tests/draft4/*.json
19− JSON-Schema-Test-Suite/tests/draft4/optional/*.json
20− README.md
21− src/draft4.json
22− test/Local/*.json
23− test/supplement/*.json
24− examples/json/*.json
1+name: hjsonschema
2+version: 0.9.0.0
3+synopsis: JSON Schema library
4+homepage: https://github.com/seagreen/hjsonschema
5+license: MIT
6+license-file: MIT-LICENSE.txt
7+author: Ian Grant Jeffries
8+maintainer: ian@housejeffries.com
9+category: Data
10+build-type: Simple
11+cabal-version: >=1.10
12+tested-with: GHC == 7.8.4, GHC == 7.10.2
13+extra-source-files: changelog.txt
14+ JSON-Schema-Test-Suite/remotes/*
15+ JSON-Schema-Test-Suite/tests/draft4/*
16+ README.md
17+ src/draft4.json
18+ tests/Local/*.json
2519
2620library
27− hs-source-dirs:
28− src
29− default-language: Haskell2010
30− default-extensions:
31− DeriveFunctor
32− DeriveGeneric
33− GeneralizedNewtypeDeriving
34− NoImplicitPrelude
35− OverloadedStrings
36− ScopedTypeVariables
37− if impl(ghc >= 8)
38− default-extensions: StrictData
39− ghc-options:
40− -Wall
41− exposed-modules:
42− JSONSchema.Draft4
43− , JSONSchema.Draft4.Failure
44− , JSONSchema.Draft4.Schema
45− , JSONSchema.Draft4.Spec
46− , JSONSchema.Fetch
47− , JSONSchema.Types
48− , JSONSchema.Validator.Draft4
49− , JSONSchema.Validator.Draft4.Any
50− , JSONSchema.Validator.Draft4.Array
51− , JSONSchema.Validator.Draft4.Number
52− , JSONSchema.Validator.Draft4.Object
53− , JSONSchema.Validator.Draft4.String
54− , JSONSchema.Validator.Reference
55− , JSONSchema.Validator.Types
56− , JSONSchema.Validator.Utils
57− other-modules:
58− JSONSchema.Validator.Draft4.Object.Properties
59− , Import
60− build-depends:
61− base >= 4.7 && < 5
62− -- 0.11 is for `.:!`:
63− , aeson >= 0.11
64− , bytestring >= 0.10
65− , containers >= 0.5
66− , file-embed >= 0.0.8
67− , filepath >= 1.3
68− , hashable >= 1.2
69− , hjsonpointer >= 1.1
70− -- 0.4.30 is for parseUrlThrow:
71− , http-client >= 0.4.30
72− , http-client-tls >= 0.3
73− , http-types >= 0.8
74− , pcre-heavy >= 1.0
75− , profunctors >= 5.0
76− , protolude >= 0.1.10
77− , QuickCheck >= 2.8
78− , safe-exceptions >= 0.1.6
79− , scientific >= 0.3
80− , unordered-containers >= 0.2
81− , text >= 1.1
82− , vector >= 0.10
21+ hs-source-dirs: src
22+ exposed-modules: Data.JsonSchema.Draft4
23+ , Data.JsonSchema.Draft4.Internal
24+ , Data.JsonSchema.Fetch
25+ , Data.Validator.Draft4
26+ , Data.Validator.Failure
27+ , Data.Validator.Reference
28+ , Data.Validator.Utils
8329
84−test-suite local
85− hs-source-dirs:
86− test
87− examples
88− main-is: Local.hs
89− type: exitcode-stdio-1.0
90− default-language: Haskell2010
91− ghc-options:
92− -Wall
93− -fno-warn-orphans
94− default-extensions:
95− DeriveGeneric
96− NoImplicitPrelude
97− OverloadedStrings
98− ScopedTypeVariables
99− other-modules:
100− Local.Failure
101− , Local.Reference
102− , Local.Validation
103− , Shared
104− -- from ./examples:
105− , AlternateSchema
106− , Simple
107− , TwoStep
108− build-depends:
109− base
110− , aeson
111− , bytestring
112− , filepath
113− , hjsonpointer
114− , hjsonschema
115− , profunctors
116− , protolude
117− , text
118− , QuickCheck
119− , unordered-containers
120− , vector
30+ other-modules: Data.JsonSchema.Draft4.Failure
31+ , Data.JsonSchema.Draft4.Schema
32+ , Data.Validator.Draft4.Any
33+ , Data.Validator.Draft4.Array
34+ , Data.Validator.Draft4.Number
35+ , Data.Validator.Draft4.Object
36+ , Data.Validator.Draft4.Object.Properties
37+ , Data.Validator.Draft4.String
38+ , Import
39+ default-language: Haskell2010
40+ default-extensions: ScopedTypeVariables
41+ OverloadedStrings
42+ ghc-options: -Wall
43+ build-depends: aeson >= 0.7 && < 0.12
44+ -- 4.6 doesn't have a Traversable Either instance:
45+ , base >= 4.7 && < 4.9
46+ , bytestring >= 0.10 && < 0.11
47+ , containers >= 0.5 && < 0.6
48+ , file-embed >= 0.0.8 && < 0.0.10
49+ , filepath >= 1.3 && < 1.5
50+ , hjsonpointer >= 0.3 && < 0.4
51+ , http-client >= 0.4.9 && < 0.5
52+ , http-types >= 0.8 && < 0.10
53+ , pcre-heavy >= 1.0 && < 1.1
54+ , QuickCheck >= 2.8.1 && < 2.9
55+ , scientific >= 0.3 && < 0.4
56+ , semigroups >= 0.18.0 && < 0.19
57+ , unordered-containers >= 0.2 && < 0.3
58+ , text >= 1.2 && < 1.3
59+ , vector >= 0.10 && < 0.12
12160
122− -- directory-1.2.5 required for `listDirectory`:
123− , directory >= 1.2.5
124− , hspec >= 2.2
61+test-suite local
62+ type: exitcode-stdio-1.0
63+ hs-source-dirs: tests
64+ main-is: Local.hs
65+ other-modules: Local.Failure
66+ , Local.Filesystem
67+ , Local.Reference
68+ , Shared
69+ default-language: Haskell2010
70+ ghc-options: -Wall -fno-warn-orphans
71+ default-extensions: OverloadedStrings
72+ build-depends: aeson
73+ , base
74+ , bytestring
75+ , filepath
76+ , hjsonpointer
77+ , hjsonschema
78+ , text
79+ , QuickCheck
80+ , unordered-containers
81+ , vector
82+ , directory >= 1.2 && < 1.3
83+ , HUnit >= 1.2 && < 1.4
84+ , tasty >= 0.11 && < 0.12
85+ , tasty-hunit >= 0.9 && < 0.10
86+ , tasty-quickcheck >= 0.8 && < 0.9
12587
12688test-suite remote
127− hs-source-dirs:
128− test
129− examples
130− main-is: Remote.hs
131− type: exitcode-stdio-1.0
132− default-language: Haskell2010
133− ghc-options:
134− -Wall
135− -fno-warn-orphans
136− default-extensions:
137− DeriveGeneric
138− NoImplicitPrelude
139− OverloadedStrings
140− ScopedTypeVariables
141− other-modules:
142− Shared
143− -- from ./examples:
144− , AlternateSchema
145− build-depends:
146− base
147− , aeson
148− , async
149− , bytestring
150− , filepath
151− , hjsonpointer
152− , hjsonschema
153− , profunctors
154− , protolude
155− , text
156− , unordered-containers
157− , vector
89+ type: exitcode-stdio-1.0
90+ hs-source-dirs: tests
91+ main-is: Remote.hs
92+ other-modules: Shared
93+ default-language: Haskell2010
94+ ghc-options: -Wall -fno-warn-orphans
95+ default-extensions: OverloadedStrings
96+ build-depends: aeson
97+ , async
98+ , base
99+ , bytestring
100+ , filepath
101+ , hjsonschema
102+ , text
103+ , vector
104+ , directory
105+ , HUnit
106+ , tasty
107+ , tasty-hunit
108+ , wai-app-static
109+ , warp
110+
111+test-suite example
112+ type: exitcode-stdio-1.0
113+ hs-source-dirs: examples
114+ main-is: Main.hs
115+ other-modules: CustomSchema
116+ , PrettyShowFailure
117+ , Standard
118+ default-language: Haskell2010
119+ ghc-options: -Wall
120+ build-depends: aeson
121+ , base
122+ , hjsonpointer
123+ , hjsonschema
124+ , tasty
125+ , tasty-hunit
126+ , text
127+ , vector
158128
159− , directory
160− , hspec
161− , wai-app-static
162− , warp
129+source-repository head
130+ type: git
131+ location: git://github.com/seagreen/hjsonschema.git
logo.jpgnew file

Binary file not shown.

shell.nixdeleted−15
@@ -1,15 +0,0 @@
1−{ghc}:
2−with (import <nixpkgs> {});
3−
4−haskell.lib.buildStackProject {
5− name = "none";
6− inherit ghc;
7− buildInputs = [
8− pcre
9−
10− git # for `git:` references in stack.yml.
11− ncurses # for intero
12− pkgconfig
13− zlib
14− ];
15−}
src/Data/JsonSchema/Draft4.hsnew file+132
@@ -0,0 +1,132 @@
1+{-# LANGUAGE ScopedTypeVariables #-}
2+{-# LANGUAGE TemplateHaskell #-}
3+
4+module Data.JsonSchema.Draft4
5+ ( Schema(..)
6+ , emptySchema
7+
8+ -- * One-step validation
9+ , HTTPValidationFailure(..)
10+ , fetchHTTPAndValidate
11+ , FilesystemValidationFailure(..)
12+ , fetchFilesystemAndValidate
13+
14+ -- * Fetching tools
15+ , SchemaWithURI(..)
16+ , ReferencedSchemas(..)
17+ , HTTPFailure(..)
18+ , referencesViaHTTP
19+ , FilesystemFailure(..)
20+ , referencesViaFilesystem
21+
22+ -- * Failure
23+ , Failure(..)
24+ , ValidatorChain(..)
25+
26+ -- * Other Draft 4 things exported just in case
27+ , checkSchema
28+ , schemaValidity
29+ , IN.runValidate
30+ , draft4Spec
31+ ) where
32+
33+import Control.Arrow (left)
34+import Data.Aeson
35+import qualified Data.ByteString.Lazy as LBS
36+import Data.FileEmbed
37+import qualified Data.HashMap.Strict as H
38+import Data.List.NonEmpty (NonEmpty)
39+import qualified Data.List.NonEmpty as N
40+import Data.Maybe (fromMaybe)
41+
42+import Data.JsonSchema.Draft4.Failure
43+import qualified Data.JsonSchema.Draft4.Internal as IN
44+import Data.JsonSchema.Draft4.Schema
45+import Data.JsonSchema.Fetch (FilesystemFailure(..),
46+ HTTPFailure(..),
47+ ReferencedSchemas(..),
48+ SchemaWithURI(..))
49+import qualified Data.JsonSchema.Fetch as FE
50+
51+data HTTPValidationFailure
52+ = HVRequest HTTPFailure
53+ | HVSchema (NonEmpty Failure)
54+ | HVData (NonEmpty Failure)
55+ deriving Show
56+
57+fetchHTTPAndValidate
58+ :: SchemaWithURI Schema
59+ -> Value
60+ -> IO (Either HTTPValidationFailure ())
61+fetchHTTPAndValidate sw v = do
62+ res <- referencesViaHTTP sw
63+ pure (g =<< f =<< left HVRequest res)
64+ where
65+ f :: ReferencedSchemas Schema
66+ -> Either HTTPValidationFailure (Value -> [Failure])
67+ f references = left HVSchema (checkSchema references sw)
68+
69+ g :: (Value -> [Failure]) -> Either HTTPValidationFailure ()
70+ g validate = case N.nonEmpty (validate v) of
71+ Nothing -> Right ()
72+ Just failures -> Left (HVData failures)
73+
74+data FilesystemValidationFailure
75+ = FVFilesystem FilesystemFailure
76+ | FVSchema (NonEmpty Failure)
77+ | FVData (NonEmpty Failure)
78+ deriving Show
79+
80+fetchFilesystemAndValidate
81+ :: SchemaWithURI Schema
82+ -> Value
83+ -> IO (Either FilesystemValidationFailure ())
84+fetchFilesystemAndValidate sw v = do
85+ res <- referencesViaFilesystem sw
86+ pure (g =<< f =<< left FVFilesystem res)
87+ where
88+ f :: ReferencedSchemas Schema
89+ -> Either FilesystemValidationFailure (Value -> [Failure])
90+ f references = left FVSchema (checkSchema references sw)
91+
92+ g :: (Value -> [Failure]) -> Either FilesystemValidationFailure ()
93+ g validate = case N.nonEmpty (validate v) of
94+ Nothing -> Right ()
95+ Just failures -> Left (FVData failures)
96+
97+-- | Check the validity of a schema and return a function to validate data.
98+checkSchema
99+ :: ReferencedSchemas Schema
100+ -> SchemaWithURI Schema
101+ -> Either (NonEmpty Failure) (Value -> [Failure])
102+checkSchema referenced schemaWithURI =
103+ case N.nonEmpty . schemaValidity . _swSchema $ schemaWithURI of
104+ Nothing -> Right (IN.runValidate referenced schemaWithURI)
105+ Just failures -> Left failures
106+
107+draft4Spec :: FE.Spec Schema
108+draft4Spec = FE.Spec IN.embedded _schemaId _schemaRef
109+
110+referencesViaHTTP
111+ :: SchemaWithURI Schema
112+ -> IO (Either HTTPFailure (ReferencedSchemas Schema))
113+referencesViaHTTP = FE.referencesViaHTTP' draft4Spec
114+
115+referencesViaFilesystem
116+ :: SchemaWithURI Schema
117+ -> IO (Either FilesystemFailure (ReferencedSchemas Schema))
118+referencesViaFilesystem = FE.referencesViaFilesystem' draft4Spec
119+
120+-- | In normal situations just use 'checkSchema', which is a combination of
121+-- 'schemaValidity' and 'runValidate'.
122+schemaValidity :: Schema -> [Failure]
123+schemaValidity = IN.runValidate referenced (SchemaWithURI d4 Nothing) . toJSON
124+ where
125+ d4 :: Schema
126+ d4 = fromMaybe (error "Schema decode failed (this should never happen)")
127+ . decode . LBS.fromStrict $ $(embedFile "src/draft4.json")
128+
129+ referenced :: ReferencedSchemas Schema
130+ referenced = ReferencedSchemas
131+ d4
132+ (H.singleton "http://json-schema.org/draft-04/schema" d4)
src/Data/JsonSchema/Draft4/Failure.hsnew file+68
@@ -0,0 +1,68 @@
1+
2+module Data.JsonSchema.Draft4.Failure where
3+
4+import qualified Data.Aeson.Pointer as P
5+
6+import qualified Data.Validator.Failure as FR
7+import Import
8+
9+-- | A version of 'FR.Failure' specialized for JSON Schema Draft 4.
10+data Failure = Failure
11+ -- NOTE: We use a data type here instead of a newtype to provide a cleaner
12+ -- API for those importing only 'Data.JsonSchema.Draft4' (which should be
13+ -- the vast majority of users). Downsides: slower and hacky. I'd appreciate
14+ -- feedback on this.
15+ { _failureValidatorsCalled :: !ValidatorChain
16+ , _failureFinalValidator :: !Value
17+ , _failureOffendingData :: !P.Pointer
18+ } deriving (Eq, Show)
19+
20+specializeForDraft4 :: FR.Failure ValidatorChain -> Failure
21+specializeForDraft4 (FR.Failure a b c) = Failure a b c
22+
23+data ValidatorChain
24+ = MultipleOf
25+ | Maximum
26+ | ExclusiveMaximum
27+ | Minimum
28+ | ExclusiveMinimum
29+
30+ | MaxLength
31+ | MinLength
32+ | PatternValidator
33+
34+ | MaxItems
35+ | MinItems
36+ | UniqueItems
37+ | Items ValidatorChain
38+ | AdditionalItemsBool
39+ | AdditionalItemsObject ValidatorChain
40+
41+ | MaxProperties
42+ | MinProperties
43+ | Required
44+ | SchemaDependency ValidatorChain
45+ | PropertyDependency
46+ | Properties ValidatorChain
47+ | PatternProperties ValidatorChain
48+ | AdditionalPropertiesBool
49+ | AdditionalPropertiesObject ValidatorChain
50+
51+ | RefResolution
52+ -- ^ Indicates a reference that failed to resolve.
53+ --
54+ -- NOTE: The language agnostic test suite doesn't specify if this should
55+ -- cause a validation error or should allow data to pass. We choose to
56+ -- return a validation error.
57+ --
58+ -- Also note that ideally we would enforce in the type system that any
59+ -- failing references be dealt with before valididation. Then this could
60+ -- be removed entirely.
61+ | Ref ValidatorChain
62+ | Enum
63+ | TypeValidator
64+ | AllOf ValidatorChain
65+ | AnyOf
66+ | OneOf
67+ | NotValidator
68+ deriving (Eq, Show)
src/Data/JsonSchema/Draft4/Internal.hsnew file+280
@@ -0,0 +1,280 @@
1+
2+module Data.JsonSchema.Draft4.Internal where
3+
4+import Data.Aeson
5+import qualified Data.HashMap.Strict as H
6+import qualified Data.List.NonEmpty as N
7+import Data.Maybe (catMaybes, fromMaybe, isJust,
8+ maybeToList)
9+import Data.Scientific
10+
11+import Data.JsonSchema.Draft4.Failure
12+import Data.JsonSchema.Draft4.Schema
13+import Data.JsonSchema.Fetch (ReferencedSchemas(..),
14+ SchemaWithURI(..))
15+import qualified Data.Validator.Draft4.Any as AN
16+import qualified Data.Validator.Draft4.Array as AR
17+import qualified Data.Validator.Draft4.Number as NU
18+import qualified Data.Validator.Draft4.Object as OB
19+import qualified Data.Validator.Draft4.String as ST
20+import Data.Validator.Failure (modFailure, setFailure)
21+import qualified Data.Validator.Failure as FR
22+import Data.Validator.Reference (updateResolutionScope)
23+import Import
24+
25+-- For GHCs before 7.10:
26+import Prelude hiding (concat)
27+
28+--------------------------------------------------
29+-- * Embedded Schemas
30+--------------------------------------------------
31+
32+-- | Return a schema's immediate subschemas.
33+--
34+-- Pass this to 'fetchReferencedSchemas' so that function can find all the
35+-- subschemas in a document. This allows 'fetchReferencedSchemas' to process
36+-- only "$ref"s and "id"s that are actual schema keywords. For example,
37+-- within a "properties" validator object an "id" key doesn't actually change
38+-- any scope, but instead serves a validator-specific function.
39+embedded :: Schema -> [Schema]
40+embedded schema = concat
41+ [ f _schemaItems
42+ (\x -> case x of
43+ AR.ItemsObject s -> pure s
44+ AR.ItemsArray ss -> ss
45+ )
46+ , f _schemaAdditionalItems
47+ (\x -> case x of
48+ AR.AdditionalObject s -> pure s
49+ _ -> mempty
50+ )
51+ , f _schemaDependencies (catMaybes . fmap checkDependency . H.elems)
52+ , f _schemaProperties H.elems
53+ , f _schemaPatternProperties H.elems
54+ , f _schemaAdditionalProperties
55+ (\x -> case x of
56+ OB.AdditionalPropertiesObject s -> pure s
57+ _ -> mempty
58+ )
59+ , f _schemaAllOf N.toList
60+ , f _schemaAnyOf N.toList
61+ , f _schemaOneOf N.toList
62+ , f _schemaNot pure
63+ , f _schemaDefinitions H.elems
64+ ]
65+ where
66+ f :: (Schema -> Maybe a) -> (a -> [Schema]) -> [Schema]
67+ f field nextLevelEmbedded = maybe mempty nextLevelEmbedded (field schema)
68+
69+ checkDependency :: OB.Dependency Schema -> Maybe Schema
70+ checkDependency (OB.PropertyDependency _) = Nothing
71+ checkDependency (OB.SchemaDependency s) = Just s
72+
73+--------------------------------------------------
74+-- * Validation (Exported from 'Data.JsonSchema.Draft4')
75+--------------------------------------------------
76+
77+-- | In normal situations just use 'checkSchema', which is a combination of
78+-- 'schemaValidity' and 'runValidate'.
79+runValidate
80+ :: ReferencedSchemas Schema
81+ -> SchemaWithURI Schema
82+ -> Value
83+ -> [Failure]
84+runValidate = (fmap.fmap.fmap.fmap) specializeForDraft4 validateAny
85+
86+--------------------------------------------------
87+-- * Validation (Main internal functions)
88+--------------------------------------------------
89+
90+validateAny
91+ :: ReferencedSchemas Schema
92+ -> SchemaWithURI Schema
93+ -> Value
94+ -> [FR.Failure ValidatorChain]
95+validateAny referenced sw x = concat
96+ [ f _schemaEnum (setFailure Enum) (fmap maybeToList . AN.enumVal)
97+ , f _schemaType (setFailure TypeValidator) (fmap maybeToList . AN.typeVal)
98+ , f _schemaAllOf (modFailure AllOf) (AN.allOf recurse)
99+ , f _schemaAnyOf (setFailure AnyOf) (fmap maybeToList . AN.anyOf recurse)
100+ , f _schemaOneOf (setFailure OneOf) (fmap maybeToList . AN.oneOf recurse)
101+ , f _schemaNot (setFailure NotValidator) (fmap maybeToList . AN.notVal recurse)
102+ , refFailures
103+ ] <> specificValidators
104+ where
105+ specificValidators :: [FR.Failure ValidatorChain]
106+ specificValidators =
107+ case x of
108+ Number y -> validateNumber (_swSchema sw) y
109+ String y -> validateString (_swSchema sw) y
110+ Array y -> validateArray referenced sw y
111+ Object y -> validateObject referenced sw y
112+ _ -> mempty
113+
114+ f = runSingle (_swSchema sw) x
115+
116+ recurse = descendNextLevel referenced sw
117+
118+ -- Since the results of the 'AN.ref' validator are fairly complicated [1]
119+ -- it's simpler not to use our 'f' helper function for it.
120+ --
121+ -- [1] A list of errors wrapped in a 'Maybe' where 'Nothing' represents
122+ -- if resolving the reference itself failed.
123+ refFailures :: [FR.Failure ValidatorChain]
124+ refFailures =
125+ case _schemaRef (_swSchema sw) of
126+ Nothing -> mempty
127+ Just reference ->
128+ maybe [FR.Failure RefResolution (toJSON reference) mempty]
129+ (fmap (modFailure Ref))
130+ $ AN.ref scope
131+ getReference
132+ (\a b -> validateAny referenced (SchemaWithURI b a))
133+ reference
134+ x
135+ where
136+ scope :: Maybe Text
137+ scope = updateResolutionScope (_swURI sw) (_schemaId (_swSchema sw))
138+
139+ getReference :: Maybe Text -> Maybe Schema
140+ getReference Nothing = Just (_rsStarting referenced)
141+ getReference (Just t) = H.lookup t (_rsSchemaMap referenced)
142+
143+validateString
144+ :: Schema
145+ -> Text
146+ -> [FR.Failure ValidatorChain]
147+validateString schema x = concat
148+ [ f _schemaMaxLength (setFailure MaxLength) (fmap maybeToList . ST.maxLength)
149+ , f _schemaMinLength (setFailure MinLength) (fmap maybeToList . ST.minLength)
150+ , f _schemaPattern (setFailure PatternValidator) (fmap maybeToList . ST.patternVal)
151+ ]
152+ where
153+ f = runSingle schema x
154+
155+validateNumber
156+ :: Schema
157+ -> Scientific
158+ -> [FR.Failure ValidatorChain]
159+validateNumber schema x = concat
160+ [ f _schemaMultipleOf (setFailure MultipleOf) (fmap maybeToList . NU.multipleOf)
161+ , f _schemaMaximum
162+ (modFailure fMax)
163+ ( fmap maybeToList
164+ . NU.maximumVal (fromMaybe False (_schemaExclusiveMaximum schema))
165+ )
166+ , f _schemaMinimum
167+ (modFailure fMin)
168+ ( fmap maybeToList
169+ . NU.minimumVal (fromMaybe False (_schemaExclusiveMinimum schema))
170+ )
171+ ]
172+ where
173+ f = runSingle schema x
174+
175+ fMax NU.Maximum = Maximum
176+ fMax NU.ExclusiveMaximum = ExclusiveMaximum
177+
178+ fMin NU.Minimum = Minimum
179+ fMin NU.ExclusiveMinimum = ExclusiveMinimum
180+
181+validateArray
182+ :: ReferencedSchemas Schema
183+ -> SchemaWithURI Schema
184+ -> Vector Value
185+ -> [FR.Failure ValidatorChain]
186+validateArray referenced (SchemaWithURI schema mUri) x = concat
187+ [ f _schemaMaxItems (setFailure MaxItems) (fmap maybeToList . AR.maxItems)
188+ , f _schemaMinItems (setFailure MinItems) (fmap maybeToList . AR.minItems)
189+ , f _schemaUniqueItems (setFailure UniqueItems) (fmap maybeToList . AR.uniqueItems)
190+ , f _schemaItems
191+ (modFailure fItems)
192+ (AR.items recurse (_schemaAdditionalItems schema))
193+ ]
194+ where
195+ f = runSingle schema x
196+
197+ recurse = descendNextLevel referenced (SchemaWithURI schema mUri)
198+
199+ fItems (AR.Items err) = Items err
200+ fItems AR.AdditionalItemsBoolFailure = AdditionalItemsBool
201+ fItems (AR.AdditionalItemsObjectFailure err) = AdditionalItemsObject err
202+
203+validateObject
204+ :: ReferencedSchemas Schema
205+ -> SchemaWithURI Schema
206+ -> HashMap Text Value
207+ -> [FR.Failure ValidatorChain]
208+validateObject referenced (SchemaWithURI schema mUri) x = concat
209+ [ f _schemaMaxProperties (setFailure MaxProperties) (fmap maybeToList . OB.maxProperties)
210+ , f _schemaMinProperties (setFailure MinProperties) (fmap maybeToList . OB.minProperties)
211+ , f _schemaRequired (setFailure Required) (fmap maybeToList . OB.required)
212+ , f _schemaDependencies (modFailure fDeps) (OB.dependencies recurse)
213+
214+ , f _schemaProperties
215+ (modFailure fProp)
216+ (OB.properties recurse
217+ (_schemaPatternProperties schema)
218+ (_schemaAdditionalProperties schema))
219+
220+ , f _schemaPatternProperties
221+ (modFailure fPatProp)
222+ (case _schemaProperties schema of
223+ Just _ -> const (const mempty)
224+ Nothing -> OB.patternProperties recurse (_schemaAdditionalProperties schema))
225+
226+ , f _schemaAdditionalProperties
227+ (modFailure fAddProp)
228+ (if isJust (_schemaProperties schema) || isJust (_schemaPatternProperties schema)
229+ then const (const mempty)
230+ else OB.additionalProperties recurse)
231+ ]
232+ where
233+ f = runSingle schema x
234+
235+ recurse = descendNextLevel referenced (SchemaWithURI schema mUri)
236+
237+ fDeps (OB.SchemaDependencyFailure err) = SchemaDependency err
238+ fDeps OB.PropertyDependencyFailure = PropertyDependency
239+
240+ fProp (OB.PropertiesFailure err) = Properties err
241+ fProp (OB.PropPatternFailure err) = PatternProperties err
242+ fProp (OB.PropAdditionalFailure a) =
243+ case a of
244+ OB.APBoolFailure -> AdditionalPropertiesBool
245+ OB.APObjectFailure err -> AdditionalPropertiesObject err
246+
247+ fPatProp (OB.PPFailure err) = PatternProperties err
248+ fPatProp (OB.PPAdditionalPropertiesFailure a) =
249+ case a of
250+ OB.APBoolFailure -> AdditionalPropertiesBool
251+ OB.APObjectFailure err -> AdditionalPropertiesObject err
252+
253+ fAddProp OB.APBoolFailure = AdditionalPropertiesBool
254+ fAddProp (OB.APObjectFailure err) = AdditionalItemsObject err
255+
256+--------------------------------------------------
257+-- * Validation (Internal utils)
258+--------------------------------------------------
259+
260+descendNextLevel
261+ :: ReferencedSchemas Schema
262+ -> SchemaWithURI Schema
263+ -> Schema
264+ -> Value
265+ -> [FR.Failure ValidatorChain]
266+descendNextLevel referenced (SchemaWithURI schema mUri) =
267+ validateAny referenced . flip SchemaWithURI scope
268+ where
269+ scope :: Maybe Text
270+ scope = updateResolutionScope mUri (_schemaId schema)
271+
272+runSingle
273+ :: Schema
274+ -> dta
275+ -> (Schema -> Maybe val)
276+ -> (err -> FR.Failure ValidatorChain)
277+ -> (val -> dta -> [err])
278+ -> [FR.Failure ValidatorChain]
279+runSingle schema dta field modifyError validate =
280+ maybe mempty (\val -> modifyError <$> validate val dta) (field schema)
src/Data/JsonSchema/Draft4/Schema.hsnew file+334
@@ -0,0 +1,334 @@
1+
2+module Data.JsonSchema.Draft4.Schema where
3+
4+import qualified Data.HashMap.Strict as H
5+import Data.List.NonEmpty (NonEmpty)
6+import Data.Maybe (fromJust, isJust)
7+import Data.Scientific
8+
9+import qualified Data.Validator.Draft4.Any as AN
10+import qualified Data.Validator.Draft4.Array as AR
11+import qualified Data.Validator.Draft4.Object as OB
12+import Data.Validator.Utils
13+import Import
14+
15+data Schema = Schema
16+ { _schemaVersion :: Maybe Text
17+ , _schemaId :: Maybe Text
18+ , _schemaRef :: Maybe Text
19+ , _schemaDefinitions :: Maybe (HashMap Text Schema)
20+ -- ^ A standardized location for embedding schemas
21+ -- to be referenced from elsewhere in the document.
22+ , _schemaOther :: HashMap Text Value
23+ -- ^ Since the JSON document this Schema was built from could
24+ -- contain schemas anywhere (not just in "definitions" or any
25+ -- of the other official keys) we save any leftover key/value
26+ -- pairs not covered by them here.
27+
28+ , _schemaMultipleOf :: Maybe Scientific
29+ , _schemaMaximum :: Maybe Scientific
30+ , _schemaExclusiveMaximum :: Maybe Bool
31+ , _schemaMinimum :: Maybe Scientific
32+ , _schemaExclusiveMinimum :: Maybe Bool
33+
34+ , _schemaMaxLength :: Maybe Int
35+ , _schemaMinLength :: Maybe Int
36+ , _schemaPattern :: Maybe Text
37+
38+ , _schemaMaxItems :: Maybe Int
39+ , _schemaMinItems :: Maybe Int
40+ , _schemaUniqueItems :: Maybe Bool
41+ , _schemaItems :: Maybe (AR.Items Schema)
42+ -- Note that '_schemaAdditionalItems' is left out of 'runValidate'
43+ -- because its functionality is handled by '_schemaItems'. It always
44+ -- validates data unless 'Items' is present.
45+ , _schemaAdditionalItems :: Maybe (AR.AdditionalItems Schema)
46+
47+ , _schemaMaxProperties :: Maybe Int
48+ , _schemaMinProperties :: Maybe Int
49+ , _schemaRequired :: Maybe OB.Required
50+ , _schemaDependencies :: Maybe (HashMap Text (OB.Dependency Schema))
51+ , _schemaProperties :: Maybe (HashMap Text Schema)
52+ , _schemaPatternProperties :: Maybe (HashMap Text Schema)
53+ , _schemaAdditionalProperties :: Maybe (OB.AdditionalProperties Schema)
54+
55+ , _schemaEnum :: Maybe AN.EnumVal
56+ , _schemaType :: Maybe AN.TypeVal
57+ , _schemaAllOf :: Maybe (NonEmpty Schema)
58+ , _schemaAnyOf :: Maybe (NonEmpty Schema)
59+ , _schemaOneOf :: Maybe (NonEmpty Schema)
60+ , _schemaNot :: Maybe Schema
61+ } deriving (Eq, Show)
62+
63+emptySchema :: Schema
64+emptySchema = Schema
65+ { _schemaVersion = Nothing
66+ , _schemaId = Nothing
67+ , _schemaRef = Nothing
68+ , _schemaDefinitions = Nothing
69+ , _schemaOther = mempty
70+
71+ , _schemaMultipleOf = Nothing
72+ , _schemaMaximum = Nothing
73+ , _schemaExclusiveMaximum = Nothing
74+ , _schemaMinimum = Nothing
75+ , _schemaExclusiveMinimum = Nothing
76+
77+ , _schemaMaxLength = Nothing
78+ , _schemaMinLength = Nothing
79+ , _schemaPattern = Nothing
80+
81+ , _schemaMaxItems = Nothing
82+ , _schemaMinItems = Nothing
83+ , _schemaUniqueItems = Nothing
84+ , _schemaItems = Nothing
85+ , _schemaAdditionalItems = Nothing
86+
87+ , _schemaMaxProperties = Nothing
88+ , _schemaMinProperties = Nothing
89+ , _schemaRequired = Nothing
90+ , _schemaDependencies = Nothing
91+ , _schemaProperties = Nothing
92+ , _schemaPatternProperties = Nothing
93+ , _schemaAdditionalProperties = Nothing
94+
95+ , _schemaEnum = Nothing
96+ , _schemaType = Nothing
97+ , _schemaAllOf = Nothing
98+ , _schemaAnyOf = Nothing
99+ , _schemaOneOf = Nothing
100+ , _schemaNot = Nothing
101+ }
102+
103+instance FromJSON Schema where
104+ parseJSON = withObject "Schema" $ \o -> do
105+ a <- o .:? "$schema"
106+ b <- o .:? "id"
107+ c <- o .:? "$ref"
108+ d <- o .:? "definitions"
109+ e <- parseJSON (Object (H.difference o internalSchemaHashMap))
110+
111+ f <- o .:? "multipleOf"
112+ g <- o .:? "maximum"
113+ h <- o .:? "exclusiveMaximum"
114+ i <- o .:? "minimum"
115+ j <- o .:? "exclusiveMinimum"
116+
117+ k <- o .:? "maxLength"
118+ l <- o .:? "minLength"
119+ m <- o .:? "pattern"
120+
121+ n <- o .:? "maxItems"
122+ o' <- o .:? "minItems"
123+ p <- o .:? "uniqueItems"
124+ q <- o .:? "items"
125+ r <- o .:? "additionalItems"
126+
127+ s <- o .:? "maxProperties"
128+ t <- o .:? "minProperties"
129+ u <- o .:? "required"
130+ v <- o .:? "dependencies"
131+ w <- o .:? "properties"
132+ x <- o .:? "patternProperties"
133+ y <- o .:? "additionalProperties"
134+
135+ z <- o .:? "enum"
136+ a2 <- o .:? "type"
137+ b2 <- fmap _unNonEmpty' <$> o .:? "allOf"
138+ c2 <- fmap _unNonEmpty' <$> o .:? "anyOf"
139+ d2 <- fmap _unNonEmpty' <$> o .:? "oneOf"
140+ e2 <- o .:? "not"
141+ pure Schema
142+ { _schemaVersion = a
143+ , _schemaId = b
144+ , _schemaRef = c
145+ , _schemaDefinitions = d
146+ , _schemaOther = e
147+
148+ , _schemaMultipleOf = f
149+ , _schemaMaximum = g
150+ , _schemaExclusiveMaximum = h
151+ , _schemaMinimum = i
152+ , _schemaExclusiveMinimum = j
153+
154+ , _schemaMaxLength = k
155+ , _schemaMinLength = l
156+ , _schemaPattern = m
157+
158+ , _schemaMaxItems = n
159+ , _schemaMinItems = o'
160+ , _schemaUniqueItems = p
161+ , _schemaItems = q
162+ , _schemaAdditionalItems = r
163+
164+ , _schemaMaxProperties = s
165+ , _schemaMinProperties = t
166+ , _schemaRequired = u
167+ , _schemaDependencies = v
168+ , _schemaProperties = w
169+ , _schemaPatternProperties = x
170+ , _schemaAdditionalProperties = y
171+
172+ , _schemaEnum = z
173+ , _schemaType = a2
174+ , _schemaAllOf = b2
175+ , _schemaAnyOf = c2
176+ , _schemaOneOf = d2
177+ , _schemaNot = e2
178+ }
179+
180+instance ToJSON Schema where
181+ -- | The way we resolve JSON Pointers to embedded schemas is by
182+ -- serializing the containing schema to a value and then resolving the
183+ -- pointer against it. This means that FromJSON and ToJSON must be
184+ -- isomorphic.
185+ --
186+ -- This influences the design choices in the library. E.g. right now
187+ -- there are two false values for "exclusiveMaximum" -- Nothing and
188+ -- Just False. We could have condensed them down by using () instead
189+ -- of Bool for "exclusiveMaximum". This would have made writing schemas
190+ -- in haskell easier, but we could no longer round trip through/from
191+ -- JSON without losing information.
192+ toJSON s = Object $ H.union (mapMaybe ($ s) internalSchemaHashMap) (toJSON <$> _schemaOther s)
193+ where
194+ -- 'mapMaybe' is provided by unordered-containers after unordered-container-2.6.0.0,
195+ -- but until that is a little older (and has time to get into Stackage etc.)
196+ -- we use our own implementation.
197+ mapMaybe :: (v1 -> Maybe v2) -> HashMap k v1 -> HashMap k v2
198+ mapMaybe f = fmap fromJust . H.filter isJust . fmap f
199+
200+-- | Internal. Separate from ToJSON because it's also used
201+-- by FromJSON to determine what keys aren't official schema
202+-- keys and therefor should be included in _schemaOther.
203+internalSchemaHashMap :: HashMap Text (Schema -> Maybe Value)
204+internalSchemaHashMap = H.fromList
205+ [ ("$schema" , f _schemaVersion)
206+ , ("id" , f _schemaId)
207+ , ("$ref" , f _schemaRef)
208+ , ("definitions" , f _schemaDefinitions)
209+
210+ , ("multipleOf" , f _schemaMultipleOf)
211+ , ("maximum" , f _schemaMaximum)
212+ , ("exclusiveMaximum" , f _schemaExclusiveMaximum)
213+ , ("minimum" , f _schemaMinimum)
214+ , ("exclusiveMinimum" , f _schemaExclusiveMinimum)
215+
216+ , ("maxLength" , f _schemaMaxLength)
217+ , ("minLength" , f _schemaMinLength)
218+ , ("pattern" , f _schemaPattern)
219+
220+ , ("maxItems" , f _schemaMaxItems)
221+ , ("minItems" , f _schemaMinItems)
222+ , ("uniqueItems" , f _schemaUniqueItems)
223+ , ("items" , f _schemaItems)
224+ , ("additionalItems" , f _schemaAdditionalItems)
225+
226+ , ("maxProperties" , f _schemaMaxProperties)
227+ , ("minProperties" , f _schemaMinProperties)
228+ , ("required" , f _schemaRequired)
229+ , ("dependencies" , f _schemaDependencies)
230+ , ("properties" , f _schemaProperties)
231+ , ("patternProperties" , f _schemaPatternProperties)
232+ , ("additionalProperties", f _schemaAdditionalProperties)
233+
234+ , ("enum" , f _schemaEnum)
235+ , ("type" , f _schemaType)
236+ , ("allOf" , f (fmap NonEmpty' . _schemaAllOf))
237+ , ("anyOf" , f (fmap NonEmpty' . _schemaAnyOf))
238+ , ("oneOf" , f (fmap NonEmpty' . _schemaOneOf))
239+ , ("not" , f _schemaNot)
240+ ]
241+ where
242+ f :: ToJSON a => (Schema -> Maybe a) -> Schema -> Maybe Value
243+ f = (fmap.fmap) toJSON
244+
245+instance Arbitrary Schema where
246+ arbitrary = sized f
247+ where
248+ maybeGen :: Gen a -> Gen (Maybe a)
249+ maybeGen a = oneof [pure Nothing, Just <$> a]
250+
251+ maybeRecurse :: Int -> Gen a -> Gen (Maybe a)
252+ maybeRecurse n a
253+ | n < 1 = pure Nothing
254+ | otherwise = maybeGen $ resize (n `div` 10) a
255+
256+ f :: Int -> Gen Schema
257+ f n = do
258+ a <- maybeGen arbitraryText
259+ b <- maybeGen arbitraryText
260+ c <- maybeGen arbitraryText
261+ -- NOTE: The next two fields are empty to generate cleaner schemas,
262+ -- but note that this means we don't test e.g. the invertability
263+ -- of these fields.
264+ d <- pure Nothing -- _schemaDefinitions
265+ e <- pure mempty -- _otherPairs
266+
267+ f' <- maybeGen arbitraryPositiveScientific
268+ g <- maybeGen arbitraryScientific
269+ h <- arbitrary
270+ i <- maybeGen arbitraryScientific
271+ j <- arbitrary
272+
273+ k <- maybeGen (getPositive <$> arbitrary)
274+ l <- maybeGen (getPositive <$> arbitrary)
275+ m <- maybeGen arbitraryText
276+
277+ n' <- maybeGen (getPositive <$> arbitrary)
278+ o <- maybeGen (getPositive <$> arbitrary)
279+ p <- arbitrary
280+ q <- maybeRecurse n arbitrary
281+ r <- maybeRecurse n arbitrary
282+
283+ s <- maybeGen (getPositive <$> arbitrary)
284+ t <- maybeGen (getPositive <$> arbitrary)
285+ u <- arbitrary
286+ v <- maybeRecurse n arbitraryHashMap
287+ w <- maybeRecurse n arbitraryHashMap
288+ x <- maybeRecurse n arbitraryHashMap
289+ y <- maybeRecurse n arbitrary
290+
291+ z <- arbitrary
292+ a2 <- arbitrary
293+ b2 <- maybeRecurse n (_unNonEmpty' <$> arbitrary)
294+ c2 <- maybeRecurse n (_unNonEmpty' <$> arbitrary)
295+ d2 <- maybeRecurse n (_unNonEmpty' <$> arbitrary)
296+ e2 <- maybeRecurse n arbitrary
297+ pure Schema
298+ { _schemaVersion = a
299+ , _schemaId = b
300+ , _schemaRef = c
301+ , _schemaDefinitions = d
302+ , _schemaOther = e
303+
304+ , _schemaMultipleOf = f'
305+ , _schemaMaximum = g
306+ , _schemaExclusiveMaximum = h
307+ , _schemaMinimum = i
308+ , _schemaExclusiveMinimum = j
309+
310+ , _schemaMaxLength = k
311+ , _schemaMinLength = l
312+ , _schemaPattern = m
313+
314+ , _schemaMaxItems = n'
315+ , _schemaMinItems = o
316+ , _schemaUniqueItems = p
317+ , _schemaItems = q
318+ , _schemaAdditionalItems = r
319+
320+ , _schemaMaxProperties = s
321+ , _schemaMinProperties = t
322+ , _schemaRequired = u
323+ , _schemaDependencies = v
324+ , _schemaProperties = w
325+ , _schemaPatternProperties = x
326+ , _schemaAdditionalProperties = y
327+
328+ , _schemaEnum = z
329+ , _schemaType = a2
330+ , _schemaAllOf = b2
331+ , _schemaAnyOf = c2
332+ , _schemaOneOf = d2
333+ , _schemaNot = e2
334+ }
src/Data/JsonSchema/Fetch.hsnew file+173
@@ -0,0 +1,173 @@
1+{-# LANGUAGE ScopedTypeVariables #-}
2+
3+module Data.JsonSchema.Fetch where
4+
5+import Control.Arrow (left)
6+import Control.Exception (catch)
7+import qualified Data.ByteString.Lazy as LBS
8+import qualified Data.ByteString as BS
9+import qualified Data.HashMap.Strict as H
10+import qualified Data.Text as T
11+import Network.HTTP.Client
12+
13+import Data.Validator.Reference (resolveReference,
14+ updateResolutionScope)
15+import Import
16+
17+-- For GHCs before 7.10:
18+import Prelude hiding (concat, sequence)
19+
20+--------------------------------------------------
21+-- * Types
22+--------------------------------------------------
23+
24+data Spec schema = Spec
25+ { _ssEmbedded :: schema -> [schema]
26+ , _ssGetId :: schema -> Maybe Text
27+ , _ssGetRef :: schema -> Maybe Text
28+ }
29+
30+data SchemaWithURI schema = SchemaWithURI
31+ { _swSchema :: !schema
32+ , _swURI :: !(Maybe Text)
33+ -- ^ Must not include a URI fragment, e.g. use
34+ -- "http://example.com/foo" not "http://example.com/foo#bar".
35+ --
36+ -- This is the URI identifying the document containing the schema.
37+ -- It's different than the schema's "id" field, which controls scope
38+ -- when resolving references contained in the schema.
39+
40+ -- TODO: Make the no URI fragment requirement unnecessary.
41+ } deriving (Eq, Show)
42+
43+-- | Keys are URIs (without URI fragments).
44+type URISchemaMap schema = HashMap Text schema
45+
46+data ReferencedSchemas schema = ReferencedSchemas
47+ { _rsStarting :: !schema
48+ -- ^ Used to resolve relative references.
49+ , _rsSchemaMap :: !(URISchemaMap schema)
50+ } deriving (Eq, Show)
51+
52+--------------------------------------------------
53+-- * Fetch via HTTP
54+--------------------------------------------------
55+
56+data HTTPFailure
57+ = HTTPParseFailure Text
58+ | RequestFailure HttpException
59+ deriving Show
60+
61+-- | Take a schema. Retrieve every document either it or its subschemas
62+-- include via the "$ref" keyword.
63+referencesViaHTTP'
64+ :: forall schema. FromJSON schema
65+ => Spec schema
66+ -> SchemaWithURI schema
67+ -> IO (Either HTTPFailure (ReferencedSchemas schema))
68+referencesViaHTTP' spec sw = do
69+ manager <- newManager defaultManagerSettings
70+ let f = referencesMethodAgnostic (get manager) spec sw
71+ catch (left HTTPParseFailure <$> f) handler
72+ where
73+ get :: Manager -> Text -> IO LBS.ByteString
74+ get man url = do
75+ request <- parseUrl (T.unpack url)
76+ responseBody <$> httpLbs request man
77+
78+ handler
79+ :: HttpException
80+ -> IO (Either HTTPFailure (ReferencedSchemas schema))
81+ handler = pure . Left . RequestFailure
82+
83+--------------------------------------------------
84+-- * Fetch via Filesystem
85+--------------------------------------------------
86+
87+data FilesystemFailure
88+ = FSParseFailure Text
89+ | ReadFailure IOError
90+ deriving Show
91+
92+referencesViaFilesystem'
93+ :: forall schema. FromJSON schema
94+ => Spec schema
95+ -> SchemaWithURI schema
96+ -> IO (Either FilesystemFailure (ReferencedSchemas schema))
97+referencesViaFilesystem' spec sw = catch (left FSParseFailure <$> f) handler
98+ where
99+ f :: IO (Either Text (ReferencedSchemas schema))
100+ f = referencesMethodAgnostic readFile' spec sw
101+
102+ readFile' :: Text -> IO LBS.ByteString
103+ readFile' = fmap LBS.fromStrict . (BS.readFile . T.unpack)
104+
105+ handler
106+ :: IOError
107+ -> IO (Either FilesystemFailure (ReferencedSchemas schema))
108+ handler = pure . Left . ReadFailure
109+
110+--------------------------------------------------
111+-- * Method Agnostic Fetching Tools
112+--------------------------------------------------
113+
114+-- | A version of 'fetchReferencedSchema's where the function to fetch
115+-- schemas is provided by the user. This allows restrictions to be added,
116+-- e.g. rejecting non-local URIs.
117+referencesMethodAgnostic
118+ :: forall schema. FromJSON schema
119+ => (Text -> IO LBS.ByteString)
120+ -> Spec schema
121+ -> SchemaWithURI schema
122+ -> IO (Either Text (ReferencedSchemas schema))
123+referencesMethodAgnostic fetchRef spec sw =
124+ (fmap.fmap) (ReferencedSchemas (_swSchema sw))
125+ (foldFunction fetchRef spec mempty sw)
126+
127+foldFunction
128+ :: forall schema. FromJSON schema
129+ => (Text -> IO LBS.ByteString)
130+ -> Spec schema
131+ -> URISchemaMap schema
132+ -> SchemaWithURI schema
133+ -> IO (Either Text (URISchemaMap schema))
134+foldFunction fetchRef spec@(Spec _ _ getRef) referenced sw =
135+ foldlM f (Right referenced) (includeSubschemas spec sw)
136+ where
137+ f :: Either Text (URISchemaMap schema)
138+ -> SchemaWithURI schema
139+ -> IO (Either Text (URISchemaMap schema))
140+ f (Left e) _ = pure (Left e)
141+ f (Right g) (SchemaWithURI schema mUri) =
142+ case newRef of
143+ Nothing -> pure (Right g)
144+ Just uri -> do
145+ bts <- fetchRef uri
146+ case eitherDecode bts of
147+ Left e -> pure . Left . T.pack $ e
148+ Right schm -> foldFunction fetchRef spec (H.insert uri schm g)
149+ (SchemaWithURI schm (Just uri))
150+ where
151+ newRef :: Maybe Text
152+ newRef
153+ | Just (Just uri,_) <- resolveReference mUri <$> getRef schema
154+ = case H.lookup uri g of
155+ Nothing -> Just uri
156+ Just _ -> Nothing
157+ | otherwise = Nothing
158+
159+-- | Return the schema passed in as an argument, as well as every
160+-- subschema contained within it.
161+includeSubschemas
162+ :: forall schema.
163+ Spec schema
164+ -> SchemaWithURI schema
165+ -> [SchemaWithURI schema]
166+includeSubschemas spec@(Spec embedded getId _) (SchemaWithURI schema mUri) =
167+ SchemaWithURI schema mUri
168+ : (includeSubschemas spec =<< subSchemas)
169+ where
170+ subSchemas :: [SchemaWithURI schema]
171+ subSchemas =
172+ (\a -> SchemaWithURI a (updateResolutionScope mUri (getId schema)))
173+ <$> embedded schema
src/Data/Validator/Draft4.hsnew file+8
@@ -0,0 +1,8 @@
1+
2+module Data.Validator.Draft4 (module Export) where
3+
4+import Data.Validator.Draft4.Any as Export
5+import Data.Validator.Draft4.Array as Export
6+import Data.Validator.Draft4.Number as Export
7+import Data.Validator.Draft4.Object as Export
8+import Data.Validator.Draft4.String as Export
src/Data/Validator/Draft4/Any.hsnew file+178
@@ -0,0 +1,178 @@
1+
2+module Data.Validator.Draft4.Any where
3+
4+import Control.Monad
5+import Data.Aeson.Types (Parser)
6+import Data.List.NonEmpty (NonEmpty)
7+import qualified Data.List.NonEmpty as N
8+import Data.Maybe
9+import Data.Scientific
10+import Data.Set (Set)
11+import qualified Data.Set as S
12+
13+import Data.Validator.Failure
14+import Data.Validator.Utils
15+import Data.Validator.Reference (resolveFragment, resolveReference)
16+import Import
17+
18+-- For GHCs before 7.10:
19+import Prelude hiding (any, elem)
20+
21+--------------------------------------------------
22+-- * $ref
23+--------------------------------------------------
24+
25+-- | Will return 'Nothing' if the reference can't be resolved.
26+ref
27+ :: forall err schema. (FromJSON schema, ToJSON schema, Show schema)
28+ => Maybe Text
29+ -> (Maybe Text -> Maybe schema)
30+ -> (Maybe Text -> schema -> Value -> [Failure err])
31+ -> Text
32+ -> Value
33+ -> Maybe [Failure err]
34+ref scope getRef f reference x = do
35+ let (mUri, mFragment) = resolveReference scope reference
36+ schema <- getRef mUri
37+ s <- resolveFragment mFragment schema
38+ Just (f mUri s x)
39+
40+--------------------------------------------------
41+-- * enum
42+--------------------------------------------------
43+
44+-- | From the spec:
45+-- <http://json-schema.org/latest/json-schema-validation.html#anchor76>
46+--
47+-- > The value of this keyword MUST be an array.
48+-- > This array MUST have at least one element.
49+-- > Elements in the array MUST be unique.
50+--
51+-- NOTE: We don't enforce the uniqueness constraint in the haskell code,
52+-- but we do in the 'FromJSON' instance.
53+newtype EnumVal
54+ = EnumVal { _unEnumVal :: NonEmpty Value }
55+ -- Given a choice, we'd prefer to enforce uniqueness through the type
56+ -- system over having at least one element. To use a 'Set' though we'd
57+ -- have to use 'OrdValue' here (there's no 'Ord' instance for plain Values)
58+ -- and we'd rather not make users mess with 'OrdValue'.
59+ deriving (Eq, Show)
60+
61+instance FromJSON EnumVal where
62+ parseJSON v = checkUnique . _unNonEmpty' =<< parseJSON v
63+ where
64+ checkUnique :: NonEmpty Value -> Parser EnumVal
65+ checkUnique a
66+ | allUniqueValues' a = pure (EnumVal a)
67+ | otherwise = fail "All elements of the Enum validator must be unique."
68+
69+instance ToJSON EnumVal where
70+ toJSON = toJSON . NonEmpty' . _unEnumVal
71+
72+instance Arbitrary EnumVal where
73+ arbitrary = do
74+ xs <- traverse (const arbitraryValue) =<< (arbitrary :: Gen [()])
75+ case N.nonEmpty (toUnique xs) of
76+ Nothing -> EnumVal . pure <$> arbitraryValue
77+ Just ne -> pure (EnumVal ne)
78+ where
79+ toUnique :: [Value] -> [Value]
80+ toUnique = fmap _unOrdValue . S.toList . S.fromList . fmap OrdValue
81+
82+enumVal :: EnumVal -> Value -> Maybe (Failure ())
83+enumVal (EnumVal vs) x
84+ | not (allUniqueValues' vs) = Nothing
85+ | x `elem` vs = Nothing
86+ | otherwise =
87+ Just $ Failure () (toJSON (NonEmpty' vs)) mempty
88+
89+--------------------------------------------------
90+-- * type
91+--------------------------------------------------
92+
93+data TypeVal
94+ = TypeValString Text
95+ | TypeValArray (Set Text)
96+ deriving (Eq, Show)
97+
98+instance FromJSON TypeVal where
99+ parseJSON v = fmap TypeValString (parseJSON v)
100+ <|> fmap TypeValArray (parseJSON v)
101+
102+instance ToJSON TypeVal where
103+ toJSON (TypeValString t) = toJSON t
104+ toJSON (TypeValArray ts) = toJSON ts
105+
106+instance Arbitrary TypeVal where
107+ arbitrary = oneof [ TypeValString <$> arbitraryText
108+ , TypeValArray <$> arbitrarySetOfText
109+ ]
110+
111+typeVal :: TypeVal -> Value -> Maybe (Failure ())
112+typeVal (TypeValString t) x = isJsonType x (S.singleton t)
113+typeVal (TypeValArray ts) x = isJsonType x ts
114+
115+isJsonType :: Value -> Set Text -> Maybe (Failure ())
116+isJsonType x ts
117+ | S.null (S.intersection okTypes ts) = Just (Failure () (toJSON ts) mempty)
118+ | otherwise = Nothing
119+ where
120+ okTypes :: Set Text
121+ okTypes =
122+ case x of
123+ Null -> S.singleton "null"
124+ (Array _) -> S.singleton "array"
125+ (Bool _) -> S.singleton "boolean"
126+ (Object _) -> S.singleton "object"
127+ (String _) -> S.singleton "string"
128+ (Number y) ->
129+ case toBoundedInteger y :: Maybe Int of
130+ Nothing -> S.singleton "number"
131+ Just _ -> S.fromList ["number", "integer"]
132+
133+--------------------------------------------------
134+-- * other
135+--------------------------------------------------
136+
137+allOf
138+ :: (schema -> Value -> [Failure err])
139+ -> NonEmpty schema
140+ -> Value
141+ -> [Failure err]
142+allOf f subSchemas x = N.toList subSchemas >>= flip f x
143+
144+anyOf
145+ :: ToJSON schema
146+ => (schema -> Value -> [Failure err])
147+ -> NonEmpty schema
148+ -> Value
149+ -> Maybe (Failure ())
150+anyOf f subSchemas x
151+ | any null (flip f x <$> subSchemas) = Nothing
152+ | otherwise = Just $ Failure () (toJSON (NonEmpty' subSchemas)) mempty
153+
154+oneOf
155+ :: forall err schema. ToJSON schema
156+ => (schema -> Value -> [Failure err])
157+ -> NonEmpty schema
158+ -> Value
159+ -> Maybe (Failure ())
160+oneOf f subSchemas x
161+ | length successes == 1 = Nothing
162+ | otherwise = Just $ Failure ()
163+ (toJSON (NonEmpty' subSchemas))
164+ mempty
165+ where
166+ successes :: [[Failure err]]
167+ successes = filter null $ flip f x <$> N.toList subSchemas
168+
169+notVal
170+ :: ToJSON schema
171+ => (schema -> Value -> [Failure err])
172+ -> schema
173+ -> Value
174+ -> Maybe (Failure ())
175+notVal f schema x =
176+ case f schema x of
177+ [] -> Just (Failure () (toJSON schema) mempty)
178+ _ -> Nothing
src/Data/Validator/Draft4/Array.hsnew file+168
@@ -0,0 +1,168 @@
1+
2+module Data.Validator.Draft4.Array where
3+
4+import Control.Monad
5+import qualified Data.Aeson.Pointer as P
6+import qualified Data.Text as T
7+import qualified Data.Vector as V
8+import Text.Read (readMaybe)
9+
10+import Data.Validator.Failure
11+import Data.Validator.Utils (allUniqueValues)
12+import Import
13+
14+-- | The spec requires "maxItems" to be non-negative.
15+maxItems :: Int -> Vector Value -> Maybe (Failure ())
16+maxItems n xs
17+ | n < 0 = Nothing
18+ | V.length xs > n = Just (Failure () (toJSON n) mempty)
19+ | otherwise = Nothing
20+
21+-- | The spec requires "minItems" to be non-negative.
22+minItems :: Int -> Vector Value -> Maybe (Failure ())
23+minItems n xs
24+ | n < 0 = Nothing
25+ | V.length xs < n = Just (Failure () (toJSON n) mempty)
26+ | otherwise = Nothing
27+
28+uniqueItems :: Bool -> Vector Value -> Maybe (Failure ())
29+uniqueItems True xs
30+ | allUniqueValues xs = Nothing
31+ | otherwise = Just (Failure () (Bool True) mempty)
32+uniqueItems False _ = Nothing
33+
34+--------------------------------------------------
35+-- * items
36+--------------------------------------------------
37+
38+data ItemsFailure err
39+ = Items err
40+ | AdditionalItemsBoolFailure
41+ | AdditionalItemsObjectFailure err
42+ deriving (Eq, Show)
43+
44+data Items schema
45+ = ItemsObject schema
46+ | ItemsArray [schema]
47+ deriving (Eq, Show)
48+
49+instance FromJSON schema => FromJSON (Items schema) where
50+ parseJSON v = fmap ItemsObject (parseJSON v)
51+ <|> fmap ItemsArray (parseJSON v)
52+
53+instance ToJSON schema => ToJSON (Items schema) where
54+ toJSON (ItemsObject hm) = toJSON hm
55+ toJSON (ItemsArray schemas) = toJSON schemas
56+
57+instance Arbitrary schema => Arbitrary (Items schema) where
58+ arbitrary = oneof [ ItemsObject <$> arbitrary
59+ , ItemsArray <$> arbitrary
60+ ]
61+
62+items
63+ :: forall err schema.
64+ (schema -> Value -> [Failure err])
65+ -> Maybe (AdditionalItems schema)
66+ -> Items schema
67+ -> Vector Value
68+ -> [Failure (ItemsFailure err)]
69+items f _ (ItemsObject subSchema) xs = zip [0..] (V.toList xs) >>= g
70+ where
71+ g :: (Int, Value) -> [Failure (ItemsFailure err)]
72+ g (index,x) = modFailure Items
73+ . addToPath (P.Token (T.pack (show index)))
74+ <$> f subSchema x
75+
76+items f mAdditional (ItemsArray subSchemas) xs = itemFailures
77+ <> additionalItemFailures
78+ where
79+ indexedValues :: [(Int, Value)]
80+ indexedValues = zip [0..] (V.toList xs)
81+
82+ itemFailures :: [Failure (ItemsFailure err)]
83+ itemFailures = join (zipWith g subSchemas indexedValues)
84+ where
85+ g :: schema -> (Int, Value) -> [Failure (ItemsFailure err)]
86+ g schema (index,x) = modFailure Items
87+ . addToPath (P.Token (T.pack (show index)))
88+ <$> f schema x
89+
90+ additionalItemFailures :: [Failure (ItemsFailure err)]
91+ additionalItemFailures =
92+ case mAdditional of
93+ Nothing -> mempty
94+ Just adi -> modFailure correctName
95+ . correctIndexes
96+ <$> additionalItems f adi extras
97+ where
98+ -- It's not great that we convert back to Vector again.
99+ extras :: Vector Value
100+ extras =
101+ V.fromList . fmap snd . drop (length subSchemas) $ indexedValues
102+
103+ -- Since 'additionalItems' only sees part of the array, but starts
104+ -- indexing from zero, we need to modify the paths it reports to
105+ -- represent invalid data so they actually represent the correct
106+ -- offsets.
107+ correctIndexes
108+ :: Failure (AdditionalItemsFailure err)
109+ -> Failure (AdditionalItemsFailure err)
110+ correctIndexes (Failure a b c) = Failure a b (fixIndex c)
111+ where
112+ fixIndex :: P.Pointer -> P.Pointer
113+ fixIndex (P.Pointer (tok:toks)) =
114+ case readMaybe . T.unpack . P._unToken $ tok of
115+ Nothing -> P.Pointer $ tok:toks
116+ Just n -> P.Pointer $
117+ (P.Token . T.pack . show $ n + length subSchemas):toks
118+ fixIndex (P.Pointer []) = P.Pointer []
119+
120+ correctName :: AdditionalItemsFailure err -> ItemsFailure err
121+ correctName AdditionalBoolFailure = AdditionalItemsBoolFailure
122+ correctName (AdditionalObjectFailure err) =
123+ AdditionalItemsObjectFailure err
124+
125+--------------------------------------------------
126+-- * additionalItems
127+--------------------------------------------------
128+
129+data AdditionalItemsFailure err
130+ = AdditionalBoolFailure
131+ | AdditionalObjectFailure err
132+ deriving (Eq, Show)
133+
134+data AdditionalItems schema
135+ = AdditionalBool Bool
136+ | AdditionalObject schema
137+ deriving (Eq, Show)
138+
139+instance FromJSON schema => FromJSON (AdditionalItems schema) where
140+ parseJSON v = fmap AdditionalBool (parseJSON v)
141+ <|> fmap AdditionalObject (parseJSON v)
142+
143+instance ToJSON schema => ToJSON (AdditionalItems schema) where
144+ toJSON (AdditionalBool b) = toJSON b
145+ toJSON (AdditionalObject hm) = toJSON hm
146+
147+instance Arbitrary schema => Arbitrary (AdditionalItems schema) where
148+ arbitrary = oneof [ AdditionalBool <$> arbitrary
149+ , AdditionalObject <$> arbitrary
150+ ]
151+
152+additionalItems
153+ :: forall err schema.
154+ (schema -> Value -> [Failure err])
155+ -> AdditionalItems schema
156+ -> Vector Value
157+ -> [Failure (AdditionalItemsFailure err)]
158+additionalItems _ (AdditionalBool b) xs
159+ | b = mempty
160+ | V.length xs > 0 = pure (Failure AdditionalBoolFailure (Bool b) mempty)
161+ | otherwise = mempty
162+additionalItems f (AdditionalObject subSchema) xs =
163+ zip [0..] (V.toList xs) >>= g
164+ where
165+ g :: (Int, Value) -> [Failure (AdditionalItemsFailure err)]
166+ g (index,x) = modFailure AdditionalObjectFailure
167+ . addToPath (P.Token (T.pack (show index)))
168+ <$> f subSchema x
src/Data/Validator/Draft4/Number.hsnew file+51
@@ -0,0 +1,51 @@
1+
2+module Data.Validator.Draft4.Number where
3+
4+import Data.Fixed (mod')
5+import Data.Scientific
6+
7+import Data.Validator.Failure
8+import Import
9+
10+-- | The spec requires "multipleOf" to be positive.
11+multipleOf :: Scientific -> Scientific -> Maybe (Failure ())
12+multipleOf n x
13+ | n <= 0 = Nothing
14+ | x `mod'` n /= 0 = Just (Failure () (toJSON n) mempty)
15+ | otherwise = Nothing
16+
17+data MaximumFailure
18+ = Maximum
19+ | ExclusiveMaximum
20+ deriving (Eq, Show)
21+
22+maximumVal
23+ :: Bool
24+ -> Scientific
25+ -> Scientific
26+ -> Maybe (Failure MaximumFailure)
27+maximumVal exclusiveMaximum n x
28+ | x `greaterThan` n = Just (Failure err (toJSON n) mempty)
29+ | otherwise = Nothing
30+ where
31+ (greaterThan, err) = if exclusiveMaximum
32+ then ((>=), ExclusiveMaximum)
33+ else ((>), Maximum)
34+
35+data MinimumFailure
36+ = Minimum
37+ | ExclusiveMinimum
38+ deriving (Eq, Show)
39+
40+minimumVal
41+ :: Bool
42+ -> Scientific
43+ -> Scientific
44+ -> Maybe (Failure MinimumFailure)
45+minimumVal exclusiveMinimum n x
46+ | x `lessThan` n = Just (Failure err (toJSON n) mempty)
47+ | otherwise = Nothing
48+ where
49+ (lessThan, err) = if exclusiveMinimum
50+ then ((<=), ExclusiveMinimum)
51+ else ((<), Minimum)
src/Data/Validator/Draft4/Object.hsnew file+147
@@ -0,0 +1,147 @@
1+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2+{-# LANGUAGE ScopedTypeVariables #-}
3+
4+module Data.Validator.Draft4.Object
5+ ( module Data.Validator.Draft4.Object
6+ , module Data.Validator.Draft4.Object.Properties
7+ ) where
8+
9+import Data.Aeson.Types (Parser)
10+import qualified Data.HashMap.Strict as H
11+import Data.Set (Set)
12+import qualified Data.Set as S
13+import qualified Data.Text as T
14+
15+import Data.Validator.Draft4.Object.Properties
16+import Data.Validator.Failure
17+import Data.Validator.Utils
18+import Import
19+
20+-- For GHCs before 7.10:
21+import Prelude hiding (all, concat,
22+ foldl)
23+
24+-- | The spec requires "maxProperties" to be non-negative.
25+maxProperties :: Int -> HashMap Text Value -> Maybe (Failure ())
26+maxProperties n x
27+ | n < 0 = Nothing
28+ | H.size x > n = Just (Failure () (toJSON n) mempty)
29+ | otherwise = Nothing
30+
31+-- | The spec requires "minProperties" to be non-negative.
32+minProperties :: Int -> HashMap Text Value -> Maybe (Failure ())
33+minProperties n x
34+ | n < 0 = Nothing
35+ | H.size x < n = Just (Failure () (toJSON n) mempty)
36+ | otherwise = Nothing
37+
38+--------------------------------------------------
39+-- * required
40+--------------------------------------------------
41+
42+-- | From the spec:
43+--
44+-- > The value of this keyword MUST be an array.
45+-- > This array MUST have at least one element.
46+-- > Elements of this array MUST be strings, and MUST be unique.
47+--
48+-- We don't enfore that 'Required' has at least one element in the
49+-- haskell code, but we do in the 'FromJSON' instance.
50+newtype Required
51+ = Required { _unRequired :: Set Text }
52+ deriving (Eq, Show, ToJSON)
53+
54+instance FromJSON Required where
55+ parseJSON v = checkUnique =<< checkSize =<< parseJSON v
56+ where
57+ checkSize :: [Text] -> Parser [Text]
58+ checkSize a
59+ | null a = fail "Required validator must not be empty."
60+ | otherwise = pure a
61+
62+ checkUnique :: [Text] -> Parser Required
63+ checkUnique a =
64+ let b = S.fromList a
65+ -- NOTE: Can use length instead of S.size in GHC 7.10 or later.
66+ in if length a == S.size b
67+ then pure (Required b)
68+ else fail "All elements of the Required validator must be unique."
69+
70+instance Arbitrary Required where
71+ arbitrary = do
72+ x <- arbitraryText -- Guarantee at least one element.
73+ xs <- (fmap.fmap) T.pack arbitrary
74+ pure . Required . S.fromList $ x:xs
75+
76+required :: Required -> HashMap Text Value -> Maybe (Failure ())
77+required (Required ts) x
78+ -- NOTE: When we no longer need to support GHCs before 7.10
79+ -- we can use null from Prelude throughout the library
80+ -- instead of specialized versions.
81+ | S.null ts = Nothing
82+ | H.null (H.difference hm x) = Nothing
83+ | otherwise = Just (Failure () (toJSON ts) mempty)
84+ where
85+ hm :: HashMap Text Bool
86+ hm = foldl (\b a -> H.insert a True b) mempty ts
87+
88+--------------------------------------------------
89+-- * dependencies
90+--------------------------------------------------
91+
92+data DependencyFailure err
93+ = SchemaDependencyFailure err
94+ | PropertyDependencyFailure
95+ deriving (Eq, Show)
96+
97+data Dependency schema
98+ = SchemaDependency schema
99+ | PropertyDependency (Set Text)
100+ deriving (Eq, Show)
101+
102+instance FromJSON schema => FromJSON (Dependency schema) where
103+ parseJSON v = fmap SchemaDependency (parseJSON v)
104+ <|> fmap PropertyDependency (parseJSON v)
105+
106+instance ToJSON schema => ToJSON (Dependency schema) where
107+ toJSON (SchemaDependency schema) = toJSON schema
108+ toJSON (PropertyDependency ts) = toJSON ts
109+
110+instance Arbitrary schema => Arbitrary (Dependency schema) where
111+ arbitrary = oneof [ SchemaDependency <$> arbitrary
112+ , PropertyDependency <$> arbitrarySetOfText
113+ ]
114+
115+-- | From the spec:
116+-- <http://json-schema.org/latest/json-schema-validation.html#anchor70>
117+--
118+-- > This keyword's value MUST be an object.
119+-- > Each value of this object MUST be either an object or an array.
120+-- >
121+-- > If the value is an object, it MUST be a valid JSON Schema.
122+-- > This is called a schema dependency.
123+-- >
124+-- > If the value is an array, it MUST have at least one element.
125+-- > Each element MUST be a string, and elements in the array MUST be unique.
126+-- > This is called a property dependency.
127+dependencies
128+ :: forall err schema. (schema -> Value -> [Failure err])
129+ -> HashMap Text (Dependency schema)
130+ -> HashMap Text Value
131+ -> [Failure (DependencyFailure err)]
132+dependencies f hm x = concat . fmap (uncurry g) . H.toList $ hm
133+ where
134+ g :: Text -> Dependency schema -> [Failure (DependencyFailure err)]
135+ g k (SchemaDependency schema)
136+ | H.member k x =
137+ modFailure SchemaDependencyFailure <$> f schema (Object x)
138+ | otherwise = mempty
139+ g k (PropertyDependency ts)
140+ | H.member k x && not allPresent =
141+ pure $ Failure PropertyDependencyFailure
142+ (toJSON (H.singleton k ts))
143+ mempty
144+ | otherwise = mempty
145+ where
146+ allPresent :: Bool
147+ allPresent = all (`H.member` x) ts
src/Data/Validator/Draft4/Object/Properties.hsnew file+190
@@ -0,0 +1,190 @@
1+{-# LANGUAGE ScopedTypeVariables #-}
2+
3+module Data.Validator.Draft4.Object.Properties where
4+
5+import Control.Monad
6+import Data.Aeson
7+import qualified Data.Aeson.Pointer as P
8+import qualified Data.HashMap.Strict as H
9+import qualified Data.Text as T
10+import Data.Text.Encoding (encodeUtf8)
11+import qualified Text.Regex.PCRE.Heavy as RE
12+
13+import Data.Validator.Failure
14+import Import
15+
16+newtype Remaining = Remaining { _unRemaining :: HashMap Text Value }
17+
18+--------------------------------------------------
19+-- * properties
20+--------------------------------------------------
21+
22+data PropertiesFailure err
23+ = PropertiesFailure err
24+ | PropPatternFailure err
25+ | PropAdditionalFailure (AdditionalPropertiesFailure err)
26+ deriving (Eq, Show)
27+
28+-- | In order of what's tried: "properties", "patternProperties",
29+-- "additionalProperties".
30+properties
31+ :: forall err schema.
32+ (schema -> Value -> [Failure err])
33+ -> Maybe (HashMap Text schema)
34+ -> Maybe (AdditionalProperties schema)
35+ -> HashMap Text schema
36+ -> HashMap Text Value
37+ -> [Failure (PropertiesFailure err)]
38+properties f mPat mAdd propertiesHm x =
39+ fmap (modFailure PropertiesFailure) propFailures
40+ <> fmap (modFailure PropPatternFailure) patternFailures
41+ <> fmap (modFailure PropAdditionalFailure) additionalFailures
42+ where
43+ propertiesAndUnmatched :: ([Failure err], Remaining)
44+ propertiesAndUnmatched = ( failures
45+ , Remaining (H.difference x propertiesHm)
46+ )
47+ where
48+ failures :: [Failure err]
49+ failures = H.toList (H.intersectionWith f propertiesHm x)
50+ >>= (\(k,vs) -> fmap (addToPath (P.Token k)) vs)
51+
52+ (propFailures, remaining1) = propertiesAndUnmatched
53+
54+ mPatProp :: Maybe (HashMap Text Value -> ([Failure err], Remaining))
55+ mPatProp = patternAndUnmatched f <$> mPat
56+
57+ patternFailures :: [Failure err]
58+ patternFailures = case mPatProp of
59+ Nothing -> mempty
60+ Just val -> fst (val x)
61+
62+ remaining2 :: Remaining
63+ remaining2 = case mPatProp of
64+ Nothing -> remaining1
65+ Just val -> snd . val . _unRemaining $ remaining1
66+
67+ additionalFailures :: [Failure (AdditionalPropertiesFailure err)]
68+ additionalFailures = case additionalProperties f <$> mAdd of
69+ Nothing -> mempty
70+ Just val -> val (_unRemaining remaining2)
71+
72+--------------------------------------------------
73+-- * patternProperties
74+--------------------------------------------------
75+
76+data PatternPropertiesFailure err
77+ = PPFailure err
78+ | PPAdditionalPropertiesFailure (AdditionalPropertiesFailure err)
79+ deriving (Eq, Show)
80+
81+patternProperties
82+ :: forall err schema.
83+ (schema -> Value -> [Failure err])
84+ -> Maybe (AdditionalProperties schema)
85+ -> HashMap Text schema
86+ -> HashMap Text Value
87+ -> [Failure (PatternPropertiesFailure err)]
88+patternProperties f mAdd patternPropertiesHm x =
89+ fmap (modFailure PPFailure) ppFailures
90+ <> fmap (modFailure PPAdditionalPropertiesFailure) addFailures
91+ where
92+ patternProps :: ([Failure err], Remaining)
93+ patternProps = patternAndUnmatched f patternPropertiesHm x
94+
95+ (ppFailures, remaining) = patternProps
96+
97+ addFailures :: [Failure (AdditionalPropertiesFailure err)]
98+ addFailures = case additionalProperties f <$> mAdd of
99+ Nothing -> mempty
100+ Just val -> val (_unRemaining remaining)
101+
102+patternAndUnmatched
103+ :: forall err schema.
104+ (schema -> Value -> [Failure err])
105+ -> HashMap Text schema
106+ -> HashMap Text Value
107+ -> ([Failure err], Remaining)
108+patternAndUnmatched f patPropertiesHm x =
109+ (H.foldlWithKey' runVals mempty perhapsMatches, remaining)
110+ where
111+ perhapsMatches :: HashMap Text (Value, [schema])
112+ perhapsMatches = H.foldlWithKey' (matchingSchemas patPropertiesHm) mempty x
113+ where
114+ matchingSchemas
115+ :: HashMap Text schema
116+ -> HashMap Text (Value, [schema])
117+ -> Text
118+ -> Value
119+ -> HashMap Text (Value, [schema])
120+ matchingSchemas subSchemas acc k v =
121+ H.insert k (v, H.foldlWithKey' (checkKey k) mempty subSchemas) acc
122+
123+ checkKey
124+ :: Text
125+ -> [schema]
126+ -> Text
127+ -> schema
128+ -> [schema]
129+ checkKey k acc r subSchema =
130+ case RE.compileM (encodeUtf8 r) mempty of
131+ Left _ -> acc
132+ Right re -> if k RE.=~ re
133+ then pure subSchema <> acc
134+ else acc
135+
136+ runVals
137+ :: [Failure err]
138+ -> Text
139+ -> (Value, [schema])
140+ -> [Failure err]
141+ runVals acc k (v,subSchemas) =
142+ (subSchemas >>= (\schema -> addToPath (P.Token k) <$> f schema v))
143+ <> acc
144+
145+ remaining :: Remaining
146+ remaining = Remaining . fmap fst . H.filter (null . snd) $ perhapsMatches
147+
148+--------------------------------------------------
149+-- * additionalProperties
150+--------------------------------------------------
151+
152+data AdditionalPropertiesFailure err
153+ = APBoolFailure
154+ | APObjectFailure err
155+ deriving (Eq, Show)
156+
157+data AdditionalProperties schema
158+ = AdditionalPropertiesBool Bool
159+ | AdditionalPropertiesObject schema
160+ deriving (Eq, Show)
161+
162+instance FromJSON schema => FromJSON (AdditionalProperties schema) where
163+ parseJSON v = fmap AdditionalPropertiesBool (parseJSON v)
164+ <|> fmap AdditionalPropertiesObject (parseJSON v)
165+
166+instance ToJSON schema => ToJSON (AdditionalProperties schema) where
167+ toJSON (AdditionalPropertiesBool b) = toJSON b
168+ toJSON (AdditionalPropertiesObject hm) = toJSON hm
169+
170+instance Arbitrary schema => Arbitrary (AdditionalProperties schema) where
171+ arbitrary = oneof [ AdditionalPropertiesBool <$> arbitrary
172+ , AdditionalPropertiesObject <$> arbitrary
173+ ]
174+
175+additionalProperties
176+ :: forall err schema.
177+ (schema -> Value -> [Failure err])
178+ -> AdditionalProperties schema
179+ -> HashMap Text Value
180+ -> [Failure (AdditionalPropertiesFailure err)]
181+additionalProperties _ (AdditionalPropertiesBool False) x
182+ | H.size x > 0 = pure $ Failure APBoolFailure (Bool False) mempty
183+ | otherwise = mempty
184+additionalProperties _ (AdditionalPropertiesBool True) _ = mempty
185+additionalProperties f (AdditionalPropertiesObject schema) x = H.toList x >>= g
186+ where
187+ g :: (Text, Value) -> [Failure (AdditionalPropertiesFailure err)]
188+ g (k,v) = modFailure APObjectFailure
189+ . addToPath (P.Token k)
190+ <$> f schema v
src/Data/Validator/Draft4/String.hsnew file+32
@@ -0,0 +1,32 @@
1+
2+module Data.Validator.Draft4.String where
3+
4+import Data.Aeson
5+import qualified Data.Text as T
6+import Data.Text.Encoding (encodeUtf8)
7+import qualified Text.Regex.PCRE.Heavy as RE
8+
9+import Data.Validator.Failure
10+import Import
11+
12+-- | The spec requires "maxLength" to be non-negative.
13+maxLength :: Int -> Text -> Maybe (Failure ())
14+maxLength n x
15+ | n <= 0 = Nothing
16+ | T.length x > n = Just (Failure () (toJSON n) mempty)
17+ | otherwise = Nothing
18+
19+-- | The spec requires "minLength" to be non-negative.
20+minLength :: Int -> Text -> Maybe (Failure ())
21+minLength n x
22+ | n <= 0 = Nothing
23+ | T.length x < n = Just (Failure () (toJSON n) mempty)
24+ | otherwise = Nothing
25+
26+patternVal :: Text -> Text -> Maybe (Failure ())
27+patternVal t x =
28+ case RE.compileM (encodeUtf8 t) mempty of
29+ Left _ -> Just (Failure () (toJSON t) mempty)
30+ Right re -> if x RE.=~ re
31+ then Nothing
32+ else Just (Failure () (toJSON t) mempty)
src/Data/Validator/Failure.hsnew file+42
@@ -0,0 +1,42 @@
1+{-# LANGUAGE ScopedTypeVariables #-}
2+
3+module Data.Validator.Failure where
4+
5+import qualified Data.Aeson.Pointer as P
6+
7+import Import
8+
9+-- For GHCs before 7.10:
10+import Prelude hiding (concat, sequence)
11+
12+-- | Validators shouldn't know more about the schema they're going to
13+-- be used with than necessary. If a validator throws errors using the
14+-- error sum type of a particular schema, then it can't be used with
15+-- other schemas later that have different error sum types (at least not
16+-- without writing partial functions).
17+--
18+-- Thus validators that can only fail in one way return 'FailureInfo's.
19+-- Validators that can fail in multiple ways return 'ValidationFailure's
20+-- along with an custom error sum type for that particular validator.
21+--
22+-- It's the job of a schema's validate function to unify the errors produced
23+-- by the validators it uses into a single error sum type for that schema.
24+-- The schema's validate function will return a 'ValidationFailure' with
25+-- that sum type as its type argument.
26+data Failure err = Failure
27+ { _failureValidatorsCalled :: !err
28+ , _failureFinalValidator :: !Value
29+ , _failureOffendingData :: !P.Pointer
30+ } deriving (Eq, Show)
31+
32+setFailure :: b -> Failure a -> Failure b
33+setFailure e (Failure _ a b) = Failure e a b
34+
35+modFailure :: (a -> b) -> Failure a -> Failure b
36+modFailure f v@(Failure a _ _) = v { _failureValidatorsCalled = f a }
37+
38+addToPath :: P.Token -> Failure a -> Failure a
39+addToPath tok v@(Failure _ _ a) = v { _failureOffendingData = addToken a }
40+ where
41+ addToken :: P.Pointer -> P.Pointer
42+ addToken (P.Pointer ts) = P.Pointer (ts <> pure tok)
src/Data/Validator/Reference.hsnew file+91
@@ -0,0 +1,91 @@
1+
2+module Data.Validator.Reference where
3+
4+-- | JSON Reference is described here:
5+-- <http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03>
6+--
7+-- And is extended for JSON Schema here:
8+-- <http://json-schema.org/latest/json-schema-core.html#anchor26>
9+--
10+-- Notes on where these functions are used:
11+--
12+-- * 'Data.JsonSchema.Fetch.includeSubschemas' uses 'updateResolutionScope'.
13+--
14+-- * 'Data.JsonSchema.Fetch.foldFunction' uses 'resolveReference'.
15+--
16+-- * 'Data.JsonSchema.Draft4.Internal' uses 'updateResolutionScope'
17+-- throughout.
18+--
19+-- * 'Data.Validator.Draft4.Any.ref' uses 'resolveReference' and
20+-- 'resolveFragment'.
21+
22+import qualified Data.Aeson.Pointer as P
23+import qualified Data.Text as T
24+import Data.Text.Encoding
25+import Network.HTTP.Types.URI (urlDecode)
26+import System.FilePath ((</>), dropFileName)
27+
28+import Import
29+
30+type URIBase = Maybe Text
31+type URIBaseAndFragment = (Maybe Text, Maybe Text)
32+
33+updateResolutionScope :: URIBase -> Maybe Text -> URIBase
34+updateResolutionScope mScope idKeyword
35+ | Just t <- idKeyword = fst . baseAndFragment $ resolveScopeAgainst mScope t
36+ | otherwise = mScope
37+
38+resolveReference :: URIBase -> Text -> URIBaseAndFragment
39+resolveReference mScope t = baseAndFragment $ resolveScopeAgainst mScope t
40+
41+resolveFragment
42+ :: (FromJSON schema, ToJSON schema, Show schema)
43+ => Maybe Text
44+ -> schema
45+ -> Maybe schema
46+resolveFragment Nothing schema = Just schema
47+resolveFragment (Just pointer) schema = do
48+ let urlDecoded = decodeUtf8 . urlDecode True . encodeUtf8 $ pointer
49+ p <- either (const Nothing) Just (P.unescape urlDecoded)
50+ x <- either (const Nothing) Just (P.resolve p (toJSON schema))
51+ case fromJSON x of
52+ Error _ -> Nothing
53+ Success schema' -> Just schema'
54+
55+--------------------------------------------------
56+-- * Helpers
57+--------------------------------------------------
58+
59+isRemoteReference :: Text -> Bool
60+isRemoteReference = T.isInfixOf "://"
61+
62+baseAndFragment :: Text -> URIBaseAndFragment
63+baseAndFragment = f . T.splitOn "#"
64+ where
65+ f :: [Text] -> URIBaseAndFragment
66+ f [x] = (g x, Nothing)
67+ f [x,y] = (g x, g y)
68+ f _ = (Nothing, Nothing)
69+
70+ g "" = Nothing
71+ g x = Just x
72+
73+resolveScopeAgainst :: Maybe Text -> Text -> Text
74+resolveScopeAgainst Nothing t = t
75+resolveScopeAgainst (Just scope) t
76+ | isRemoteReference t = t
77+ | otherwise = smartAppend
78+ where
79+ -- There shouldn't be a fragment at the end of a scope URI,
80+ -- but just in case a user leaves one in we want to be sure
81+ -- to cut it off before appending.
82+ smartAppend :: Text
83+ smartAppend =
84+ case baseAndFragment scope of
85+ (Just base,_) ->
86+ case T.unpack t of
87+ -- We want "/foo" and "#/bar" to combine into
88+ -- "/foo#/bar" not "/foo/#/bar".
89+ '#':_ -> base <> t
90+ _ -> T.pack (dropFileName (T.unpack base) </> T.unpack t)
91+ _ -> t
src/Data/Validator/Utils.hsnew file+122
@@ -0,0 +1,122 @@
1+
2+module Data.Validator.Utils where
3+
4+import Control.Arrow
5+import qualified Data.HashMap.Strict as H
6+import Data.List.NonEmpty (NonEmpty)
7+import qualified Data.List.NonEmpty as N
8+import Data.Scientific (Scientific, fromFloatDigits)
9+import Data.Set (Set)
10+import qualified Data.Set as S
11+import qualified Data.Text as T
12+import qualified Data.Vector as V
13+
14+import Import
15+
16+--------------------------------------------------
17+-- * QuickCheck
18+--------------------------------------------------
19+
20+arbitraryText :: Gen Text
21+arbitraryText = T.pack <$> arbitrary
22+
23+arbitraryScientific :: Gen Scientific
24+arbitraryScientific = (fromFloatDigits :: Double -> Scientific) <$> arbitrary
25+
26+arbitraryPositiveScientific :: Gen Scientific
27+arbitraryPositiveScientific = (fromFloatDigits :: Double -> Scientific)
28+ . getPositive
29+ <$> arbitrary
30+
31+arbitraryValue :: Gen Value
32+arbitraryValue = sized f
33+ where
34+ f :: Int -> Gen Value
35+ f n | n <= 1 = oneof nonRecursive
36+ | otherwise = oneof $
37+ fmap (Array . V.fromList) (traverse (const (f (n `div` 10)))
38+ =<< (arbitrary :: Gen [()]))
39+ : fmap (Object . H.fromList) (traverse (const (g (n `div` 10)))
40+ =<< (arbitrary :: Gen [()]))
41+ : nonRecursive
42+
43+ g :: Int -> Gen (Text, Value)
44+ g n = (,) <$> arbitraryText <*> f n
45+
46+ nonRecursive :: [Gen Value]
47+ nonRecursive =
48+ [ pure Null
49+ , Bool <$> arbitrary
50+ , String <$> arbitraryText
51+ , Number <$> arbitraryScientific
52+ ]
53+
54+arbitraryHashMap :: Arbitrary a => Gen (HashMap Text a)
55+arbitraryHashMap = H.fromList . fmap (first T.pack) <$> arbitrary
56+
57+arbitrarySetOfText :: Gen (Set Text)
58+arbitrarySetOfText = S.fromList . fmap T.pack <$> arbitrary
59+
60+newtype NonEmpty' a = NonEmpty' { _unNonEmpty' :: NonEmpty a }
61+
62+instance FromJSON a => FromJSON (NonEmpty' a) where
63+ parseJSON v = do
64+ xs <- parseJSON v
65+ case N.nonEmpty xs of
66+ Nothing -> fail "Must have at least one item."
67+ Just ne -> pure (NonEmpty' ne)
68+
69+instance ToJSON a => ToJSON (NonEmpty' a) where
70+ toJSON = toJSON . N.toList . _unNonEmpty'
71+
72+instance Arbitrary a => Arbitrary (NonEmpty' a) where
73+ arbitrary = do
74+ xs <- arbitrary
75+ case N.nonEmpty xs of
76+ Nothing -> NonEmpty' . pure <$> arbitrary
77+ Just ne -> pure (NonEmpty' ne)
78+
79+--------------------------------------------------
80+-- * allUniqueValues
81+--------------------------------------------------
82+
83+allUniqueValues :: Vector Value -> Bool
84+allUniqueValues = allUnique . fmap OrdValue . V.toList
85+
86+-- NOTE: When we no longer support GHC 7.8 we can generalize
87+-- allUnique to work on any Foldable and remove this function.
88+allUniqueValues' :: NonEmpty Value -> Bool
89+allUniqueValues' = allUnique . fmap OrdValue . N.toList
90+
91+allUnique :: (Ord a) => [a] -> Bool
92+allUnique xs = S.size (S.fromList xs) == length xs
93+
94+-- | OrdValue's Ord instance needs benchmarking, but it allows us to
95+-- use our 'allUnique' function instead of O(n^2) nub, so it's probably
96+-- worth it.
97+newtype OrdValue = OrdValue { _unOrdValue :: Value } deriving Eq
98+
99+instance Ord OrdValue where
100+ (OrdValue Null) `compare` (OrdValue Null) = EQ
101+ (OrdValue Null) `compare` _ = LT
102+ _ `compare` (OrdValue Null) = GT
103+
104+ (OrdValue (Bool x)) `compare` (OrdValue (Bool y)) = x `compare` y
105+ (OrdValue (Bool _)) `compare` _ = LT
106+ _ `compare` (OrdValue (Bool _)) = GT
107+
108+ (OrdValue (Number x)) `compare` (OrdValue (Number y)) = x `compare` y
109+ (OrdValue (Number _)) `compare` _ = LT
110+ _ `compare` (OrdValue (Number _)) = GT
111+
112+ (OrdValue (String x)) `compare` (OrdValue (String y)) = x `compare` y
113+ (OrdValue (String _)) `compare` _ = LT
114+ _ `compare` (OrdValue (String _)) = GT
115+
116+ (OrdValue (Array xs)) `compare` (OrdValue (Array ys)) =
117+ (OrdValue <$> xs) `compare` (OrdValue <$> ys)
118+ (OrdValue (Array _)) `compare` _ = LT
119+ _ `compare` (OrdValue (Array _)) = GT
120+
121+ (OrdValue (Object x)) `compare` (OrdValue (Object y)) =
122+ H.toList (OrdValue <$> x) `compare` H.toList (OrdValue <$> y)
src/Import.hs+9−16
@@ -1,19 +1,12 @@
11
2−module Import (module Export, fromJSONEither) where
2+module Import (module Export) where
33
4−import Protolude as Export
5−
6−import Data.Aeson as Export
4+import Control.Applicative as Export
5+import Data.Aeson as Export
6+import Data.Foldable as Export
77import Data.HashMap.Strict as Export (HashMap)
8−import Data.List.NonEmpty as Export (NonEmpty)
9−import Data.Vector as Export (Vector)
10−import Test.QuickCheck as Export hiding (Failure, Result, Success,
11− (.&.))
12−
13−import qualified Data.Text as T
14−
15−fromJSONEither :: FromJSON a => Value -> Either Text a
16−fromJSONEither a =
17− case fromJSON a of
18− Error e -> Left (T.pack e)
19− Success b -> Right b
8+import Data.Monoid as Export
9+import Data.Text as Export (Text)
10+import Data.Traversable as Export
11+import Data.Vector as Export (Vector)
12+import Test.QuickCheck as Export hiding (Failure, Result, Success)
src/JSONSchema/Draft4.hsdeleted−186
@@ -1,186 +0,0 @@
1−{-# LANGUAGE TemplateHaskell #-}
2−
3−module JSONSchema.Draft4
4− ( -- * Draft 4 Schema
5− SchemaWithURI(..)
6− , Schema(..)
7− , SC.emptySchema
8−
9− -- * One-step validation (getting references over HTTP)
10− , fetchHTTPAndValidate
11− , HTTPValidationFailure(..)
12− , FE.HTTPFailure(..)
13− , SchemaInvalid(..)
14−
15− -- * One-step validation (getting references from the filesystem)
16− , fetchFilesystemAndValidate
17− , FilesystemValidationFailure(..)
18− , FE.FilesystemFailure(..)
19−
20− -- * Validation failure
21− , Invalid(..)
22− , ValidatorFailure(..)
23−
24− -- * Fetching tools
25− , URISchemaMap(..)
26− , referencesViaHTTP
27− , referencesViaFilesystem
28−
29− -- * Other Draft 4 things exported just in case
30− , metaSchema
31− , metaSchemaBytes
32− , schemaValidity
33− , referencesValidity
34− , checkSchema
35− , draft4FetchInfo
36− ) where
37−
38−import Import
39−
40−import qualified Data.ByteString as BS
41−import Data.FileEmbed (embedFile, makeRelativeToProject)
42−import qualified Data.HashMap.Strict as HM
43−import qualified Data.List.NonEmpty as NE
44−import Data.Maybe (fromMaybe)
45−
46−import JSONSchema.Draft4.Failure (Invalid(..), SchemaInvalid(..),
47− ValidatorFailure(..))
48−import JSONSchema.Draft4.Schema (Schema)
49−import qualified JSONSchema.Draft4.Schema as SC
50−import qualified JSONSchema.Draft4.Spec as Spec
51−import JSONSchema.Fetch (SchemaWithURI(..), URISchemaMap(..))
52−import qualified JSONSchema.Fetch as FE
53−
54−data HTTPValidationFailure
55− = HVRequest FE.HTTPFailure
56− | HVSchema SchemaInvalid
57− | HVData Invalid
58− deriving Show
59−
60−-- | Fetch recursively referenced schemas over HTTP, check that both the
61−-- original and referenced schemas are valid, then validate then data.
62−fetchHTTPAndValidate
63− :: SchemaWithURI Schema
64− -> Value
65− -> IO (Either HTTPValidationFailure ())
66−fetchHTTPAndValidate sw v = do
67− res <- referencesViaHTTP sw
68− pure (g =<< f =<< first HVRequest res)
69− where
70− f :: FE.URISchemaMap Schema
71− -> Either HTTPValidationFailure (Value -> [ValidatorFailure])
72− f references = first HVSchema (checkSchema references sw)
73−
74− g :: (Value -> [ValidatorFailure]) -> Either HTTPValidationFailure ()
75− g val = case NE.nonEmpty (val v) of
76− Nothing -> Right ()
77− Just failures -> Left (HVData Invalid
78− { _invalidSchema = _swSchema sw
79− , _invalidInstance = v
80− , _invalidFailures = failures
81− })
82−
83−data FilesystemValidationFailure
84− = FVRead FE.FilesystemFailure
85− | FVSchema SchemaInvalid
86− | FVData Invalid
87− deriving (Show, Eq)
88−
89−-- | Fetch recursively referenced schemas from the filesystem, check
90−-- that both the original and referenced schemas are valid, then validate
91−-- the data.
92−fetchFilesystemAndValidate
93− :: SchemaWithURI Schema
94− -> Value
95− -> IO (Either FilesystemValidationFailure ())
96−fetchFilesystemAndValidate sw v = do
97− res <- referencesViaFilesystem sw
98− pure (g =<< f =<< first FVRead res)
99− where
100− f :: FE.URISchemaMap Schema
101− -> Either FilesystemValidationFailure (Value -> [ValidatorFailure])
102− f references = first FVSchema (checkSchema references sw)
103−
104− g :: (Value -> [ValidatorFailure]) -> Either FilesystemValidationFailure ()
105− g val = case NE.nonEmpty (val v) of
106− Nothing -> Right ()
107− Just invalid -> Left (FVData Invalid
108− { _invalidSchema = _swSchema sw
109− , _invalidInstance = v
110− , _invalidFailures = invalid
111− })
112−
113−-- | An instance of 'JSONSchema.Fetch.FetchInfo' specialized for
114−-- JSON Schema Draft 4.
115−draft4FetchInfo :: FE.FetchInfo Schema
116−draft4FetchInfo = FE.FetchInfo Spec.embedded SC._schemaId SC._schemaRef
117−
118−-- | Fetch the schemas recursively referenced by a starting schema over HTTP.
119−referencesViaHTTP
120− :: SchemaWithURI Schema
121− -> IO (Either FE.HTTPFailure (FE.URISchemaMap Schema))
122−referencesViaHTTP = FE.referencesViaHTTP' draft4FetchInfo
123−
124−-- | Fetch the schemas recursively referenced by a starting schema from
125−-- the filesystem.
126−referencesViaFilesystem
127− :: SchemaWithURI Schema
128− -> IO (Either FE.FilesystemFailure (FE.URISchemaMap Schema))
129−referencesViaFilesystem = FE.referencesViaFilesystem' draft4FetchInfo
130−
131−-- | Checks if a schema and a set of referenced schemas are valid.
132−--
133−-- Return a function to validate data.
134−checkSchema
135− :: FE.URISchemaMap Schema
136− -> SchemaWithURI Schema
137− -> Either SchemaInvalid (Value -> [ValidatorFailure])
138−checkSchema sm sw =
139− case NE.nonEmpty failures of
140− Just fs -> Left (SchemaInvalid fs)
141− Nothing -> Right (Spec.specValidate sm sw)
142− where
143− failures :: [(Maybe Text, NonEmpty ValidatorFailure)]
144− failures =
145− let refFailures = first Just <$> referencesValidity sm
146− in case NE.nonEmpty (schemaValidity (_swSchema sw)) of
147− Nothing -> refFailures
148− Just errs -> (Nothing,errs) : refFailures
149−
150−metaSchema :: Schema
151−metaSchema =
152− fromMaybe (panic "Schema decode failed (this should never happen)")
153− . decodeStrict
154− $ metaSchemaBytes
155−
156−metaSchemaBytes :: BS.ByteString
157−metaSchemaBytes =
158− $(makeRelativeToProject "src/draft4.json" >>= embedFile)
159−
160−-- | Check that a schema itself is valid
161−-- (if so the returned list will be empty).
162−schemaValidity :: Schema -> [ValidatorFailure]
163−schemaValidity =
164− Spec.specValidate schemaMap (SchemaWithURI metaSchema Nothing) . toJSON
165− where
166− schemaMap :: URISchemaMap Schema
167− schemaMap =
168− URISchemaMap (HM.singleton "http://json-schema.org/draft-04/schema"
169− metaSchema)
170−
171−-- | Check that a set of referenced schemas are valid
172−-- (if so the returned list will be empty).
173−referencesValidity
174− :: FE.URISchemaMap Schema
175− -> [(Text, NonEmpty ValidatorFailure)]
176− -- ^ The first item of the tuple is the URI of a schema, the second
177− -- is that schema's validation errors.
178−referencesValidity = HM.foldlWithKey' f mempty . FE._unURISchemaMap
179− where
180− f :: [(Text, NonEmpty ValidatorFailure)]
181− -> Text
182− -> Schema
183− -> [(Text, NonEmpty ValidatorFailure)]
184− f acc k v = case NE.nonEmpty (schemaValidity v) of
185− Nothing -> acc
186− Just errs -> (k,errs) : acc
src/JSONSchema/Draft4/Failure.hsdeleted−58
@@ -1,58 +0,0 @@
1−module JSONSchema.Draft4.Failure where
2−
3−import Import
4−
5−import JSONSchema.Draft4.Schema (Schema)
6−import qualified JSONSchema.Validator.Draft4 as VAL
7−
8−-- | Used to report an entire instance being invalidated, as opposed
9−-- to the failure of a single validator.
10−data Invalid = Invalid
11− { _invalidSchema :: Schema
12− , _invalidInstance :: Value
13− , _invalidFailures :: NonEmpty ValidatorFailure
14− } deriving (Eq, Show)
15−
16−data ValidatorFailure
17− = FailureMultipleOf VAL.MultipleOfInvalid
18− | FailureMaximum VAL.MaximumInvalid
19− | FailureMinimum VAL.MinimumInvalid
20−
21− | FailureMaxLength VAL.MaxLengthInvalid
22− | FailureMinLength VAL.MinLengthInvalid
23− | FailurePattern VAL.PatternInvalid
24−
25− | FailureMaxItems VAL.MaxItemsInvalid
26− | FailureMinItems VAL.MinItemsInvalid
27− | FailureUniqueItems VAL.UniqueItemsInvalid
28− | FailureItems (VAL.ItemsInvalid ValidatorFailure)
29− | FailureAdditionalItems (VAL.AdditionalItemsInvalid ValidatorFailure)
30−
31− | FailureMaxProperties VAL.MaxPropertiesInvalid
32− | FailureMinProperties VAL.MinPropertiesInvalid
33− | FailureRequired VAL.RequiredInvalid
34− | FailureDependencies (VAL.DependenciesInvalid ValidatorFailure)
35− | FailurePropertiesRelated (VAL.PropertiesRelatedInvalid ValidatorFailure)
36−
37− | FailureRef (VAL.RefInvalid ValidatorFailure)
38− | FailureEnum VAL.EnumInvalid
39− | FailureType VAL.TypeValidatorInvalid
40− | FailureAllOf (VAL.AllOfInvalid ValidatorFailure)
41− | FailureAnyOf (VAL.AnyOfInvalid ValidatorFailure)
42− | FailureOneOf (VAL.OneOfInvalid ValidatorFailure)
43− | FailureNot VAL.NotValidatorInvalid
44− deriving (Eq, Show)
45−
46−-- | A description of why a schema (or one of its reference) is itself
47−-- invalid.
48−--
49−-- 'Nothing' indicates the starting schema. 'Just' indicates a referenced
50−-- schema. The contents of the 'Just' is the schema's URI.
51−--
52−-- NOTE: 'HashMap (Maybe Text) Invalid' would be a nicer way of
53−-- defining this, but then we lose the guarantee that there's at least
54−-- one key.
55−newtype SchemaInvalid
56− = SchemaInvalid {
57− _unSchemaInvalid :: NonEmpty (Maybe Text, NonEmpty ValidatorFailure) }
58− deriving (Eq, Show)
src/JSONSchema/Draft4/Schema.hsdeleted−341
@@ -1,341 +0,0 @@
1−module JSONSchema.Draft4.Schema where
2−
3−import Import hiding (mapMaybe)
4−
5−import qualified Data.HashMap.Strict as HM
6−import Data.List.NonEmpty (NonEmpty)
7−import Data.Maybe (fromJust, isJust)
8−import Data.Scientific
9−import qualified Data.Set as Set
10−import qualified Data.Text as T
11−
12−import qualified JSONSchema.Validator.Draft4 as D4
13−import JSONSchema.Validator.Utils
14−
15−data Schema = Schema
16− { _schemaVersion :: Maybe Text
17− , _schemaId :: Maybe Text
18− , _schemaRef :: Maybe Text
19− , _schemaDefinitions :: Maybe (HashMap Text Schema)
20− -- ^ A standardized location for embedding schemas
21− -- to be referenced from elsewhere in the document.
22− , _schemaOther :: HashMap Text Value
23− -- ^ Since the JSON document this schema was built from could
24− -- contain schemas anywhere (not just in "definitions" or any
25− -- of the other official keys) we save any leftover key/value
26− -- pairs not covered by them here.
27− --
28− -- TODO: This field is the source of most of the complication in this
29− -- module and needs to be removed. It should be doable, though it will
30− -- involve some modification to the fetching code.
31−
32− , _schemaMultipleOf :: Maybe Scientific
33− , _schemaMaximum :: Maybe Scientific
34− , _schemaExclusiveMaximum :: Maybe Bool
35− , _schemaMinimum :: Maybe Scientific
36− , _schemaExclusiveMinimum :: Maybe Bool
37−
38− , _schemaMaxLength :: Maybe Int
39− , _schemaMinLength :: Maybe Int
40− , _schemaPattern :: Maybe Text
41−
42− , _schemaMaxItems :: Maybe Int
43− , _schemaMinItems :: Maybe Int
44− , _schemaUniqueItems :: Maybe Bool
45− , _schemaItems :: Maybe (D4.Items Schema)
46− -- Note that '_schemaAdditionalItems' is left out of 'runValidate'
47− -- because its functionality is handled by '_schemaItems'. It always
48− -- validates data unless 'Items' is present.
49− , _schemaAdditionalItems :: Maybe (D4.AdditionalItems Schema)
50−
51− , _schemaMaxProperties :: Maybe Int
52− , _schemaMinProperties :: Maybe Int
53− , _schemaRequired :: Maybe (Set Text)
54− , _schemaDependencies :: Maybe (HashMap Text (D4.Dependency Schema))
55− , _schemaProperties :: Maybe (HashMap Text Schema)
56− , _schemaPatternProperties :: Maybe (HashMap Text Schema)
57− , _schemaAdditionalProperties :: Maybe (D4.AdditionalProperties Schema)
58−
59− , _schemaEnum :: Maybe (NonEmpty Value)
60− , _schemaType :: Maybe D4.TypeValidator
61− , _schemaAllOf :: Maybe (NonEmpty Schema)
62− , _schemaAnyOf :: Maybe (NonEmpty Schema)
63− , _schemaOneOf :: Maybe (NonEmpty Schema)
64− , _schemaNot :: Maybe Schema
65− } deriving (Eq, Show)
66−
67−emptySchema :: Schema
68−emptySchema = Schema
69− { _schemaVersion = Nothing
70− , _schemaId = Nothing
71− , _schemaRef = Nothing
72− , _schemaDefinitions = Nothing
73− , _schemaOther = mempty
74−
75− , _schemaMultipleOf = Nothing
76− , _schemaMaximum = Nothing
77− , _schemaExclusiveMaximum = Nothing
78− , _schemaMinimum = Nothing
79− , _schemaExclusiveMinimum = Nothing
80−
81− , _schemaMaxLength = Nothing
82− , _schemaMinLength = Nothing
83− , _schemaPattern = Nothing
84−
85− , _schemaMaxItems = Nothing
86− , _schemaMinItems = Nothing
87− , _schemaUniqueItems = Nothing
88− , _schemaItems = Nothing
89− , _schemaAdditionalItems = Nothing
90−
91− , _schemaMaxProperties = Nothing
92− , _schemaMinProperties = Nothing
93− , _schemaRequired = Nothing
94− , _schemaDependencies = Nothing
95− , _schemaProperties = Nothing
96− , _schemaPatternProperties = Nothing
97− , _schemaAdditionalProperties = Nothing
98−
99− , _schemaEnum = Nothing
100− , _schemaType = Nothing
101− , _schemaAllOf = Nothing
102− , _schemaAnyOf = Nothing
103− , _schemaOneOf = Nothing
104− , _schemaNot = Nothing
105− }
106−
107−instance FromJSON Schema where
108− parseJSON = withObject "Schema" $ \o -> do
109− a <- o .:! "$schema"
110− b <- o .:! "id"
111− c <- o .:! "$ref"
112− d <- o .:! "definitions"
113− e <- parseJSON (Object (HM.difference o internalSchemaHashMap))
114−
115− f <- o .:! "multipleOf"
116− g <- o .:! "maximum"
117− h <- o .:! "exclusiveMaximum"
118− i <- o .:! "minimum"
119− j <- o .:! "exclusiveMinimum"
120−
121− k <- o .:! "maxLength"
122− l <- o .:! "minLength"
123− m <- o .:! "pattern"
124−
125− n <- o .:! "maxItems"
126− o' <- o .:! "minItems"
127− p <- o .:! "uniqueItems"
128− q <- o .:! "items"
129− r <- o .:! "additionalItems"
130−
131− s <- o .:! "maxProperties"
132− t <- o .:! "minProperties"
133− u <- o .:! "required"
134− v <- o .:! "dependencies"
135− w <- o .:! "properties"
136− x <- o .:! "patternProperties"
137− y <- o .:! "additionalProperties"
138−
139− z <- o .:! "enum"
140− a2 <- o .:! "type"
141− b2 <- fmap _unNonEmpty' <$> o .:! "allOf"
142− c2 <- fmap _unNonEmpty' <$> o .:! "anyOf"
143− d2 <- fmap _unNonEmpty' <$> o .:! "oneOf"
144− e2 <- o .:! "not"
145− pure Schema
146− { _schemaVersion = a
147− , _schemaId = b
148− , _schemaRef = c
149− , _schemaDefinitions = d
150− , _schemaOther = e
151−
152− , _schemaMultipleOf = f
153− , _schemaMaximum = g
154− , _schemaExclusiveMaximum = h
155− , _schemaMinimum = i
156− , _schemaExclusiveMinimum = j
157−
158− , _schemaMaxLength = k
159− , _schemaMinLength = l
160− , _schemaPattern = m
161−
162− , _schemaMaxItems = n
163− , _schemaMinItems = o'
164− , _schemaUniqueItems = p
165− , _schemaItems = q
166− , _schemaAdditionalItems = r
167−
168− , _schemaMaxProperties = s
169− , _schemaMinProperties = t
170− , _schemaRequired = u
171− , _schemaDependencies = v
172− , _schemaProperties = w
173− , _schemaPatternProperties = x
174− , _schemaAdditionalProperties = y
175−
176− , _schemaEnum = z
177− , _schemaType = a2
178− , _schemaAllOf = b2
179− , _schemaAnyOf = c2
180− , _schemaOneOf = d2
181− , _schemaNot = e2
182− }
183−
184−instance ToJSON Schema where
185− -- | The way we resolve JSON Pointers to embedded schemas is by
186− -- serializing the containing schema to a value and then resolving the
187− -- pointer against it. This means that FromJSON and ToJSON must be
188− -- isomorphic.
189− --
190− -- This influences the design choices in the library. E.g. right now
191− -- there are two false values for "exclusiveMaximum" -- Nothing and
192− -- Just False. We could have condensed them down by using () instead
193− -- of Bool for "exclusiveMaximum". This would have made writing schemas
194− -- in haskell easier, but we could no longer round trip through/from
195− -- JSON without losing information.
196− toJSON s = Object $ HM.union (mapMaybe ($ s) internalSchemaHashMap)
197− (toJSON <$> _schemaOther s)
198− where
199− -- 'mapMaybe' is provided by unordered-containers after
200− -- unordered-container-2.6.0.0, but until that is a little older
201− -- (and has time to get into Stackage etc.) we use our own
202− -- implementation.
203− mapMaybe :: (v1 -> Maybe v2) -> HashMap k v1 -> HashMap k v2
204− mapMaybe f = fmap fromJust . HM.filter isJust . fmap f
205−
206−-- | Internal. Separate from ToJSON because it's also used
207−-- by FromJSON to determine what keys aren't official schema
208−-- keys and therefor should be included in _schemaOther.
209−internalSchemaHashMap :: HashMap Text (Schema -> Maybe Value)
210−internalSchemaHashMap = HM.fromList
211− [ ("$schema" , f _schemaVersion)
212− , ("id" , f _schemaId)
213− , ("$ref" , f _schemaRef)
214− , ("definitions" , f _schemaDefinitions)
215−
216− , ("multipleOf" , f _schemaMultipleOf)
217− , ("maximum" , f _schemaMaximum)
218− , ("exclusiveMaximum" , f _schemaExclusiveMaximum)
219− , ("minimum" , f _schemaMinimum)
220− , ("exclusiveMinimum" , f _schemaExclusiveMinimum)
221−
222− , ("maxLength" , f _schemaMaxLength)
223− , ("minLength" , f _schemaMinLength)
224− , ("pattern" , f _schemaPattern)
225−
226− , ("maxItems" , f _schemaMaxItems)
227− , ("minItems" , f _schemaMinItems)
228− , ("uniqueItems" , f _schemaUniqueItems)
229− , ("items" , f _schemaItems)
230− , ("additionalItems" , f _schemaAdditionalItems)
231−
232− , ("maxProperties" , f _schemaMaxProperties)
233− , ("minProperties" , f _schemaMinProperties)
234− , ("required" , f _schemaRequired)
235− , ("dependencies" , f _schemaDependencies)
236− , ("properties" , f _schemaProperties)
237− , ("patternProperties" , f _schemaPatternProperties)
238− , ("additionalProperties", f _schemaAdditionalProperties)
239−
240− , ("enum" , f _schemaEnum)
241− , ("type" , f _schemaType)
242− , ("allOf" , f (fmap NonEmpty' . _schemaAllOf))
243− , ("anyOf" , f (fmap NonEmpty' . _schemaAnyOf))
244− , ("oneOf" , f (fmap NonEmpty' . _schemaOneOf))
245− , ("not" , f _schemaNot)
246− ]
247− where
248− f :: ToJSON a => (Schema -> Maybe a) -> Schema -> Maybe Value
249− f = (fmap.fmap) toJSON
250−
251−instance Arbitrary Schema where
252− arbitrary = sized f
253− where
254− maybeGen :: Gen a -> Gen (Maybe a)
255− maybeGen a = oneof [pure Nothing, Just <$> a]
256−
257− maybeRecurse :: Int -> Gen a -> Gen (Maybe a)
258− maybeRecurse n a
259− | n < 1 = pure Nothing
260− | otherwise = maybeGen $ resize (n `div` 10) a
261−
262− f :: Int -> Gen Schema
263− f n = do
264− a <- maybeGen arbitraryText
265− b <- maybeGen arbitraryText
266− c <- maybeGen arbitraryText
267− -- NOTE: The next two fields are empty to generate cleaner
268− -- schemas, but note that this means we don't test the
269− -- invertability of these fields.
270− d <- pure Nothing -- _schemaDefinitions
271− e <- pure mempty -- _otherPairs
272−
273− f' <- maybeGen arbitraryPositiveScientific
274− g <- maybeGen arbitraryScientific
275− h <- arbitrary
276− i <- maybeGen arbitraryScientific
277− j <- arbitrary
278−
279− k <- maybeGen (getPositive <$> arbitrary)
280− l <- maybeGen (getPositive <$> arbitrary)
281− m <- maybeGen arbitraryText
282−
283− n' <- maybeGen (getPositive <$> arbitrary)
284− o <- maybeGen (getPositive <$> arbitrary)
285− p <- arbitrary
286− q <- maybeRecurse n arbitrary
287− r <- maybeRecurse n arbitrary
288−
289− s <- maybeGen (getPositive <$> arbitrary)
290− t <- maybeGen (getPositive <$> arbitrary)
291− u <- maybeGen (Set.map T.pack <$> arbitrary)
292− v <- maybeRecurse n arbitraryHashMap
293− w <- maybeRecurse n arbitraryHashMap
294− x <- maybeRecurse n arbitraryHashMap
295− y <- maybeRecurse n arbitrary
296−
297− z <- maybeRecurse n ( fmap _unArbitraryValue . _unNonEmpty'
298− <$> arbitrary)
299− a2 <- arbitrary
300− b2 <- maybeRecurse n (_unNonEmpty' <$> arbitrary)
301− c2 <- maybeRecurse n (_unNonEmpty' <$> arbitrary)
302− d2 <- maybeRecurse n (_unNonEmpty' <$> arbitrary)
303− e2 <- maybeRecurse n arbitrary
304− pure Schema
305− { _schemaVersion = a
306− , _schemaId = b
307− , _schemaRef = c
308− , _schemaDefinitions = d
309− , _schemaOther = e
310−
311− , _schemaMultipleOf = f'
312− , _schemaMaximum = g
313− , _schemaExclusiveMaximum = h
314− , _schemaMinimum = i
315− , _schemaExclusiveMinimum = j
316−
317− , _schemaMaxLength = k
318− , _schemaMinLength = l
319− , _schemaPattern = m
320−
321− , _schemaMaxItems = n'
322− , _schemaMinItems = o
323− , _schemaUniqueItems = p
324− , _schemaItems = q
325− , _schemaAdditionalItems = r
326−
327− , _schemaMaxProperties = s
328− , _schemaMinProperties = t
329− , _schemaRequired = u
330− , _schemaDependencies = v
331− , _schemaProperties = w
332− , _schemaPatternProperties = x
333− , _schemaAdditionalProperties = y
334−
335− , _schemaEnum = z
336− , _schemaType = a2
337− , _schemaAllOf = b2
338− , _schemaAnyOf = c2
339− , _schemaOneOf = d2
340− , _schemaNot = e2
341− }
src/JSONSchema/Draft4/Spec.hsdeleted−150
@@ -1,150 +0,0 @@
1−module JSONSchema.Draft4.Spec where
2−
3−import Import
4−
5−import Data.Maybe (fromMaybe)
6−import Data.Profunctor (Profunctor(..))
7−
8−import JSONSchema.Draft4.Failure
9−import JSONSchema.Draft4.Schema (Schema(..), emptySchema)
10−import JSONSchema.Fetch (SchemaWithURI(..), URISchemaMap(..))
11−import qualified JSONSchema.Fetch as FE
12−import JSONSchema.Types (Spec(..))
13−import qualified JSONSchema.Types as JT
14−import JSONSchema.Validator.Draft4
15−import JSONSchema.Validator.Reference (BaseURI(..), Scope(..),
16− updateResolutionScope)
17−
18−-- | An implementation of 'JT.embedded'.
19−embedded :: Schema -> ([Schema], [Schema])
20−embedded s =
21− JT.embedded (d4Spec mempty mempty (Scope s Nothing (BaseURI Nothing))) s
22−
23−specValidate
24− :: URISchemaMap Schema
25− -> SchemaWithURI Schema
26− -> Value
27− -> [ValidatorFailure]
28−specValidate schemaMap sw =
29− JT.validate (d4Spec schemaMap visited scope) (_swSchema sw)
30− where
31− visited :: VisitedSchemas
32− visited = VisitedSchemas [(Nothing, Nothing)]
33−
34− scope :: Scope Schema
35− scope = Scope
36− { _topLevelDocument = _swSchema sw
37− , _documentURI = _swURI sw
38− , _currentBaseURI = updateResolutionScope (BaseURI (_swURI sw))
39− (_schemaId (_swSchema sw))
40− }
41−
42−validateSubschema
43− :: URISchemaMap Schema
44− -> VisitedSchemas
45− -> Scope Schema
46− -> Schema
47− -> Value
48− -> [ValidatorFailure]
49−validateSubschema schemaMap visited scope schema =
50− JT.validate (d4Spec schemaMap visited newScope) schema
51− where
52− newScope :: Scope Schema
53− newScope = scope
54− { _currentBaseURI = updateResolutionScope (_currentBaseURI scope)
55− (_schemaId schema)
56− }
57−
58−d4Spec
59− :: URISchemaMap Schema
60− -> VisitedSchemas
61− -> Scope Schema
62− -> Spec Schema ValidatorFailure
63−d4Spec schemaMap visited scope = Spec $
64− [ dimap
65− (fmap Ref . _schemaRef)
66− FailureRef
67− (refValidator (FE.getReference schemaMap) updateScope valRef visited scope)
68− ]
69−
70− <> fmap (lmap disableIfRefPresent)
71− [ dimap (fmap MultipleOf . _schemaMultipleOf) FailureMultipleOf multipleOfValidator
72− , dimap
73− (\s -> Maximum (fromMaybe False (_schemaExclusiveMaximum s)) <$> _schemaMaximum s)
74− FailureMaximum
75− maximumValidator
76− , dimap
77− (\s -> Minimum (fromMaybe False (_schemaExclusiveMinimum s)) <$> _schemaMinimum s)
78− FailureMinimum
79− minimumValidator
80−
81− , dimap (fmap MaxLength . _schemaMaxLength) FailureMaxLength maxLengthValidator
82− , dimap (fmap MinLength . _schemaMinLength) FailureMinLength minLengthValidator
83− , dimap (fmap PatternValidator . _schemaPattern) FailurePattern patternValidator
84−
85− , dimap (fmap MaxItems . _schemaMaxItems) FailureMaxItems maxItemsValidator
86− , dimap (fmap MinItems . _schemaMinItems) FailureMinItems minItemsValidator
87− , dimap (fmap UniqueItems . _schemaUniqueItems) FailureUniqueItems uniqueItemsValidator
88− , dimap
89− (\s -> ItemsRelated
90− { _irItems = _schemaItems s
91− , _irAdditional = _schemaAdditionalItems s
92− })
93− (\err -> case err of
94− IRInvalidItems e -> FailureItems e
95− IRInvalidAdditional e -> FailureAdditionalItems e)
96− (itemsRelatedValidator descend)
97− , lmap (fmap Definitions . _schemaDefinitions) definitionsEmbedded
98−
99− , dimap
100− (fmap MaxProperties . _schemaMaxProperties)
101− FailureMaxProperties
102− maxPropertiesValidator
103− , dimap
104− (fmap MinProperties . _schemaMinProperties)
105− FailureMinProperties
106− minPropertiesValidator
107− , dimap (fmap Required . _schemaRequired) FailureRequired requiredValidator
108− , dimap
109− (fmap DependenciesValidator . _schemaDependencies)
110− FailureDependencies
111− (dependenciesValidator descend)
112− , dimap
113− (\s -> PropertiesRelated
114− { _propProperties = _schemaProperties s
115− , _propPattern = _schemaPatternProperties s
116− , _propAdditional = _schemaAdditionalProperties s
117− })
118− FailurePropertiesRelated
119− (propertiesRelatedValidator descend)
120−
121− , dimap (fmap EnumValidator . _schemaEnum) FailureEnum enumValidator
122− , dimap (fmap TypeContext . _schemaType) FailureType typeValidator
123− , dimap (fmap AllOf . _schemaAllOf) FailureAllOf (allOfValidator lateral)
124− , dimap (fmap AnyOf . _schemaAnyOf) FailureAnyOf (anyOfValidator lateral)
125− , dimap (fmap OneOf . _schemaOneOf) FailureOneOf (oneOfValidator lateral)
126− , dimap (fmap NotValidator . _schemaNot) FailureNot (notValidator lateral)
127− ]
128− where
129− disableIfRefPresent :: Schema -> Schema
130− disableIfRefPresent schema =
131− case _schemaRef schema of
132− Nothing -> schema
133− Just _ -> emptySchema
134−
135− updateScope :: BaseURI -> Schema -> BaseURI
136− updateScope uri schema = updateResolutionScope uri (_schemaId schema)
137−
138− valRef
139− :: VisitedSchemas
140− -> Scope Schema
141− -> Schema
142− -> Value
143− -> [ValidatorFailure]
144− valRef vis sc = JT.validate (d4Spec schemaMap vis sc)
145−
146− descend :: Schema -> Value -> [ValidatorFailure]
147− descend = validateSubschema schemaMap mempty scope
148−
149− lateral :: Schema -> Value -> [ValidatorFailure]
150− lateral = validateSubschema schemaMap visited scope
src/JSONSchema/Fetch.hsdeleted−175
@@ -1,175 +0,0 @@
1−module JSONSchema.Fetch where
2−
3−import Import
4−
5−import qualified Control.Exception.Safe as Safe
6−import Control.Monad (foldM)
7−import qualified Data.ByteString as BS
8−import qualified Data.ByteString.Lazy as LBS
9−import qualified Data.HashMap.Strict as HM
10−import qualified Data.Semigroup as S
11−import qualified Data.Text as T
12−import qualified Network.HTTP.Client as NC
13−import qualified Network.HTTP.Client.TLS as NCTLS
14−
15−import JSONSchema.Validator.Reference (BaseURI(..), resolveReference,
16− updateResolutionScope)
17−
18−--------------------------------------------------
19−-- * Types
20−--------------------------------------------------
21−
22−-- | This is all the fetching functions need to know about a particular
23−-- JSON Schema draft, e.g. JSON Schema Draft 4.
24−data FetchInfo schema = FetchInfo
25− { _fiEmbedded :: schema -> ([schema], [schema])
26− , _fiId :: schema -> Maybe Text
27− , _fiRef :: schema -> Maybe Text
28− }
29−
30−-- | Keys are URIs (without URI fragments).
31−newtype URISchemaMap schema
32− = URISchemaMap { _unURISchemaMap :: HashMap Text schema }
33− deriving (Eq, Show, S.Semigroup, Monoid)
34−
35−-- | A top-level schema along with its location.
36−data SchemaWithURI schema = SchemaWithURI
37− { _swSchema :: !schema
38− , _swURI :: !(Maybe Text)
39− -- ^ This is the URI from which the document was originally fetched.
40− -- It's different than the schema's "id" field, which controls scope
41− -- when resolving references contained in the schema.
42− } deriving (Eq, Show)
43−
44−getReference :: URISchemaMap schema -> Text -> Maybe schema
45−getReference schemaMap t = HM.lookup t (_unURISchemaMap schemaMap)
46−
47−--------------------------------------------------
48−-- * Fetch via HTTP
49−--------------------------------------------------
50−
51−data HTTPFailure
52− = HTTPParseFailure Text
53− | HTTPRequestFailure NC.HttpException
54− deriving Show
55−
56−-- | Take a schema. Retrieve every document either it or its subschemas
57−-- include via the "$ref" keyword.
58−referencesViaHTTP'
59− :: forall schema. FromJSON schema
60− => FetchInfo schema
61− -> SchemaWithURI schema
62− -> IO (Either HTTPFailure (URISchemaMap schema))
63−referencesViaHTTP' info sw = do
64− manager <- NC.newManager NCTLS.tlsManagerSettings
65− let f = referencesMethodAgnostic (getURL manager) info sw
66− Safe.catch (first HTTPParseFailure <$> f) handler
67− where
68− getURL :: NC.Manager -> Text -> IO BS.ByteString
69− getURL man url = do
70− request <- NC.parseUrlThrow (T.unpack url)
71− LBS.toStrict . NC.responseBody <$> NC.httpLbs request man
72−
73− handler
74− :: NC.HttpException
75− -> IO (Either HTTPFailure (URISchemaMap schema))
76− handler = pure . Left . HTTPRequestFailure
77−
78−--------------------------------------------------
79−-- * Fetch via Filesystem
80−--------------------------------------------------
81−
82−data FilesystemFailure
83− = FSParseFailure Text
84− | FSReadFailure IOException
85− deriving (Show, Eq)
86−
87−referencesViaFilesystem'
88− :: forall schema. FromJSON schema
89− => FetchInfo schema
90− -> SchemaWithURI schema
91− -> IO (Either FilesystemFailure (URISchemaMap schema))
92−referencesViaFilesystem' info sw =
93− Safe.catch (first FSParseFailure <$> f) handler
94− where
95− f :: IO (Either Text (URISchemaMap schema))
96− f = referencesMethodAgnostic (BS.readFile . T.unpack) info sw
97−
98− handler
99− :: IOException
100− -> IO (Either FilesystemFailure (URISchemaMap schema))
101− handler = pure . Left . FSReadFailure
102−
103−--------------------------------------------------
104−-- * Method Agnostic Fetching Tools
105−--------------------------------------------------
106−
107−-- | A version of 'fetchReferencedSchema's where the function to fetch
108−-- schemas is provided by the user. This allows restrictions to be added,
109−-- e.g. rejecting non-local URIs.
110−referencesMethodAgnostic
111− :: forall schema. FromJSON schema
112− => (Text -> IO BS.ByteString)
113− -> FetchInfo schema
114− -> SchemaWithURI schema
115− -> IO (Either Text (URISchemaMap schema))
116−referencesMethodAgnostic fetchRef info =
117− getRecursiveReferences fetchRef info (URISchemaMap mempty)
118−
119−getRecursiveReferences
120− :: forall schema. FromJSON schema
121− => (Text -> IO BS.ByteString)
122− -> FetchInfo schema
123− -> URISchemaMap schema
124− -> SchemaWithURI schema
125− -> IO (Either Text (URISchemaMap schema))
126−getRecursiveReferences fetchRef info referenced sw =
127− foldM f (Right referenced) (includeSubschemas info sw)
128− where
129− f :: Either Text (URISchemaMap schema)
130− -> SchemaWithURI schema
131− -> IO (Either Text (URISchemaMap schema))
132− f (Left e) _ = pure (Left e)
133− f (Right (URISchemaMap schemaMap)) (SchemaWithURI schema mURI) =
134− case newRef of
135− Nothing -> pure (Right (URISchemaMap schemaMap))
136− Just uri -> do
137− bts <- fetchRef uri
138− case eitherDecodeStrict bts of
139− Left e -> pure . Left . T.pack $ e
140− Right s -> getRecursiveReferences
141− fetchRef
142− info
143− (URISchemaMap (HM.insert uri s schemaMap))
144− (SchemaWithURI s (Just uri))
145− where
146− newRef :: Maybe Text
147− newRef = do
148− ref <- _fiRef info schema
149−
150− -- Consider the reference before updating the scope.
151− -- If it's a only a fragment this isn't referencing
152− -- a new document.
153− void (fst (resolveReference (BaseURI Nothing) ref))
154−
155− uri <- fst (resolveReference (BaseURI mURI) ref)
156− case HM.lookup uri schemaMap of
157− Nothing -> Just uri
158− Just _ -> Nothing
159−
160−-- | Return the schema passed in as an argument, as well as every
161−-- subschema contained within it.
162−includeSubschemas
163− :: forall schema.
164− FetchInfo schema
165− -> SchemaWithURI schema
166− -> [SchemaWithURI schema]
167−includeSubschemas info (SchemaWithURI schema mURI) =
168− SchemaWithURI schema mURI
169− : (includeSubschemas info =<< subSchemas)
170− where
171− subSchemas :: [SchemaWithURI schema]
172− subSchemas =
173− let newScope = updateResolutionScope (BaseURI mURI) (_fiId info schema)
174− updateScope s = SchemaWithURI s (_unBaseURI newScope)
175− in updateScope <$> uncurry (<>) (_fiEmbedded info schema)
src/JSONSchema/Types.hsdeleted−35
@@ -1,35 +0,0 @@
1−module JSONSchema.Types where
2−
3−import Import
4−
5−import JSONSchema.Validator.Types (Validator(..))
6−
7−newtype Spec schema err
8− = Spec { _unSpec :: [Validator schema schema err] }
9−
10−-- | Return a schema's immediate subschemas.
11−--
12−-- The first list is subschemas validating the same level of the document,
13−-- the second list is subschemas validating lower levels (see
14−-- 'JSONSchema.Validator.Types.Fail' for a full explanation).
15−embedded :: Spec schema a -> schema -> ([schema], [schema])
16−embedded spec schema =
17− let embeds = (\val -> _embedded val schema) <$> _unSpec spec
18− in foldl' (\(a,b) (x,y) -> (x <> a, y <> b)) (mempty, mempty) embeds
19−
20−validate
21− :: Spec schema err
22− -> schema
23− -> Value
24− -> [err]
25−validate spec schema v =
26− (\val -> _validate val schema v) =<< _unSpec spec
27−
28−-- | A basic schema type that doesn't impose much structure.
29−--
30−-- 'JSONSchema.Draft4' doesn't use this, but instead uses the record based
31−-- one defined in 'JSONSchema.Draft4.Schema' to make it easier to write
32−-- draft 4 schemas in Haskell.
33−newtype Schema
34− = Schema { _unSchema :: HashMap Text Value }
35− deriving (Eq, Show, FromJSON, ToJSON)
src/JSONSchema/Validator/Draft4.hsdeleted−242
@@ -1,242 +0,0 @@
1−-- | Turn the validation functions into actual 'Validator's.
2−--
3−-- This is frankly a lot of busywork. It can perhaps be moved into the
4−-- validator modules themselves once we're sure this is the right design.
5−module JSONSchema.Validator.Draft4
6− ( module JSONSchema.Validator.Draft4
7− , module Export
8− ) where
9−
10−import Import
11−
12−import qualified Data.HashMap.Strict as HM
13−import qualified Data.List.NonEmpty as NE
14−
15−import JSONSchema.Validator.Draft4.Any as Export
16−import JSONSchema.Validator.Draft4.Array as Export
17−import JSONSchema.Validator.Draft4.Number as Export
18−import JSONSchema.Validator.Draft4.Object as Export
19−import JSONSchema.Validator.Draft4.String as Export
20−import JSONSchema.Validator.Reference (BaseURI(..), Scope(..))
21−import JSONSchema.Validator.Types (Validator(..))
22−
23−-- | For internal use.
24−--
25−-- Take a validation function, a possibly existing validator, and some data.
26−-- If the validator is exists and can validate the type of data we have,
27−-- attempt to do so and return any failures.
28−run :: FromJSON b => (a -> b -> Maybe c) -> Maybe a -> Value -> [c]
29−run _ Nothing _ = mempty
30−run f (Just a) b =
31− case fromJSONEither b of
32− Left _ -> mempty
33− Right c -> maybeToList (f a c)
34−
35−-- | For internal use.
36−noEmbedded :: a -> ([b], [b])
37−noEmbedded = const (mempty, mempty)
38−
39−--------------------------------------------------
40−-- * Numbers
41−--------------------------------------------------
42−
43−multipleOfValidator :: Validator a (Maybe MultipleOf) MultipleOfInvalid
44−multipleOfValidator = Validator noEmbedded (run multipleOfVal)
45−
46−maximumValidator :: Validator a (Maybe Maximum) MaximumInvalid
47−maximumValidator = Validator noEmbedded (run maximumVal)
48−
49−minimumValidator :: Validator a (Maybe Minimum) MinimumInvalid
50−minimumValidator = Validator noEmbedded (run minimumVal)
51−
52−--------------------------------------------------
53−-- * Strings
54−--------------------------------------------------
55−
56−maxLengthValidator :: Validator a (Maybe MaxLength) MaxLengthInvalid
57−maxLengthValidator = Validator noEmbedded (run maxLengthVal)
58−
59−minLengthValidator :: Validator a (Maybe MinLength) MinLengthInvalid
60−minLengthValidator = Validator noEmbedded (run minLengthVal)
61−
62−patternValidator :: Validator a (Maybe PatternValidator) PatternInvalid
63−patternValidator = Validator noEmbedded (run patternVal)
64−
65−--------------------------------------------------
66−-- * Arrays
67−--------------------------------------------------
68−
69−maxItemsValidator :: Validator a (Maybe MaxItems) MaxItemsInvalid
70−maxItemsValidator = Validator noEmbedded (run maxItemsVal)
71−
72−minItemsValidator :: Validator a (Maybe MinItems) MinItemsInvalid
73−minItemsValidator = Validator noEmbedded (run minItemsVal)
74−
75−uniqueItemsValidator :: Validator a (Maybe UniqueItems) UniqueItemsInvalid
76−uniqueItemsValidator = Validator noEmbedded (run uniqueItemsVal)
77−
78−-- TODO: Add tests to the language agnostic test suite to
79−-- make sure @"additionalItems"@ subschemas are embedded correctly.
80−itemsRelatedValidator
81− :: (schema -> Value -> [err])
82− -> Validator schema (ItemsRelated schema) (ItemsRelatedInvalid err)
83−itemsRelatedValidator f =
84− Validator
85− (\a -> ( mempty
86− , case _irItems a of
87− Just (ItemsObject b) -> pure b
88− Just (ItemsArray cs) -> cs
89− Nothing -> mempty
90− <> case _irAdditional a of
91− Just (AdditionalObject b) -> pure b
92− _ -> mempty
93− ))
94− (\a b -> case fromJSONEither b of
95− Left _ -> mempty
96− Right c -> itemsRelatedVal f a c)
97−
98−--------------------------------------------------
99−-- * Objects
100−--------------------------------------------------
101−
102−maxPropertiesValidator
103− :: Validator
104− a
105− (Maybe MaxProperties)
106− MaxPropertiesInvalid
107−maxPropertiesValidator = Validator noEmbedded (run maxPropertiesVal)
108−
109−minPropertiesValidator
110− :: Validator
111− a
112− (Maybe MinProperties)
113− MinPropertiesInvalid
114−minPropertiesValidator = Validator noEmbedded (run minPropertiesVal)
115−
116−requiredValidator :: Validator a (Maybe Required) RequiredInvalid
117−requiredValidator = Validator noEmbedded (run requiredVal)
118−
119−dependenciesValidator
120− :: (schema -> Value -> [err])
121− -> Validator
122− schema
123− (Maybe (DependenciesValidator schema))
124− (DependenciesInvalid err)
125−dependenciesValidator f =
126− Validator
127− (maybe mempty ( (\a -> (mempty, a))
128− . catMaybes . fmap checkDependency
129− . HM.elems . _unDependenciesValidator
130− ))
131− (run (dependenciesVal f))
132− where
133− checkDependency :: Dependency schema -> Maybe schema
134− checkDependency (PropertyDependency _) = Nothing
135− checkDependency (SchemaDependency s) = Just s
136−
137−propertiesRelatedValidator
138− :: (schema -> Value -> [err])
139− -> Validator
140− schema
141− (PropertiesRelated schema)
142− (PropertiesRelatedInvalid err)
143−propertiesRelatedValidator f =
144− Validator
145− (\a -> ( mempty
146− , HM.elems (fromMaybe mempty (_propProperties a))
147− <> HM.elems (fromMaybe mempty (_propPattern a))
148− <> case _propAdditional a of
149− Just (AdditionalPropertiesObject b) -> [b]
150− _ -> mempty
151− ))
152− (\a b -> case fromJSONEither b of
153− Left _ -> mempty
154− Right c -> maybeToList (propertiesRelatedVal f a c))
155−
156−newtype Definitions schema
157− = Definitions { _unDefinitions :: HashMap Text schema }
158− deriving (Eq, Show)
159−
160−instance FromJSON schema => FromJSON (Definitions schema) where
161− parseJSON = withObject "Definitions" $ \o ->
162− Definitions <$> o .: "definitions"
163−
164−definitionsEmbedded
165− :: Validator
166− schema
167− (Maybe (Definitions schema))
168− err
169−definitionsEmbedded =
170− Validator
171− (\a -> case a of
172− Just (Definitions b) -> (mempty, HM.elems b)
173− Nothing -> (mempty, mempty))
174− (const (const mempty))
175−
176−--------------------------------------------------
177−-- * Any
178−--------------------------------------------------
179−
180−refValidator
181− :: (FromJSON schema, ToJSON schema)
182− => (Text -> Maybe schema)
183− -> (BaseURI -> schema -> BaseURI)
184− -> (VisitedSchemas -> Scope schema -> schema -> Value -> [err])
185− -> VisitedSchemas
186− -> Scope schema
187− -> Validator a (Maybe Ref) (RefInvalid err)
188−refValidator getRef updateScope f visited scope =
189− Validator
190− noEmbedded
191− (run (refVal getRef updateScope f visited scope))
192−
193−enumValidator :: Validator a (Maybe EnumValidator) EnumInvalid
194−enumValidator = Validator noEmbedded (run enumVal)
195−
196−typeValidator :: Validator a (Maybe TypeContext) TypeValidatorInvalid
197−typeValidator = Validator noEmbedded (run typeVal)
198−
199−allOfValidator
200− :: (schema -> Value -> [err])
201− -> Validator schema (Maybe (AllOf schema)) (AllOfInvalid err)
202−allOfValidator f =
203− Validator
204− (\a -> case a of
205− Just (AllOf b) -> (NE.toList b, mempty)
206− Nothing -> (mempty, mempty))
207− (run (allOfVal f))
208−
209−anyOfValidator
210− :: (schema -> Value -> [err])
211− -> Validator schema (Maybe (AnyOf schema)) (AnyOfInvalid err)
212−anyOfValidator f =
213− Validator
214− (\a -> case a of
215− Just (AnyOf b) -> (NE.toList b, mempty)
216− Nothing -> (mempty, mempty))
217− (run (anyOfVal f))
218−
219−oneOfValidator
220− :: ToJSON schema
221− => (schema -> Value -> [err])
222− -> Validator schema (Maybe (OneOf schema)) (OneOfInvalid err)
223−oneOfValidator f =
224− Validator
225− (\a -> case a of
226− Just (OneOf b) -> (NE.toList b, mempty)
227− Nothing -> (mempty, mempty))
228− (run (oneOfVal f))
229−
230−notValidator
231− :: ToJSON schema
232− => (schema -> Value -> [err])
233− -> Validator
234− schema
235− (Maybe (NotValidator schema))
236− NotValidatorInvalid
237−notValidator f =
238− Validator
239− (\a -> case a of
240− Just (NotValidator b) -> (pure b, mempty)
241− Nothing -> (mempty, mempty))
242− (run (notVal f))
src/JSONSchema/Validator/Draft4/Any.hsdeleted−509
@@ -1,509 +0,0 @@
1−module JSONSchema.Validator.Draft4.Any where
2−
3−import Import hiding ((<>))
4−
5−import Data.Aeson.TH (constructorTagModifier)
6−import Data.Char (toLower)
7−import qualified Data.HashMap.Strict as HM
8−import Data.List.NonEmpty (NonEmpty((:|)))
9−import qualified Data.List.NonEmpty as NE
10−import qualified Data.Scientific as SCI
11−import Data.Semigroup
12−import Data.Set (Set)
13−import qualified Data.Set as Set
14−import Data.Text.Encoding.Error (UnicodeException)
15−import qualified JSONPointer as JP
16−import Network.HTTP.Types.URI (urlDecode)
17−
18−import JSONSchema.Validator.Reference (BaseURI(..), Scope(..),
19− URIAndFragment,
20− resolveReference)
21−import qualified JSONSchema.Validator.Utils as UT
22−
23−--------------------------------------------------
24−-- * $ref
25−--------------------------------------------------
26−
27−newtype Ref
28− = Ref { _unRef :: Text }
29− deriving (Eq, Show)
30−
31−instance FromJSON Ref where
32− parseJSON = withObject "Ref" $ \o ->
33− Ref <$> o .: "$ref"
34−
35−data RefInvalid err
36− = RefResolution Text
37− -- ^ Indicates a reference that failed to resolve.
38− --
39− -- NOTE: The language agnostic test suite doesn't specify if this should
40− -- cause a validation error or should allow data to pass. We choose to
41− -- return a validation error.
42− --
43− -- Also note that ideally we would enforce in the type system that any
44− -- failing references be dealt with before valididation. Then this could
45− -- be removed entirely.
46− | RefPointerResolution JSONPointerError
47− | RefLoop Text VisitedSchemas URIAndFragment
48− | RefInvalid Text Value (NonEmpty err)
49− -- ^ 'Text' is the URI and 'Value' is the linked schema.
50− deriving (Eq, Show)
51−
52−newtype VisitedSchemas
53− = VisitedSchemas { _unVisited :: [URIAndFragment] }
54− deriving (Eq, Show, Semigroup, Monoid)
55−
56−refVal
57− :: forall err schema. (FromJSON schema, ToJSON schema)
58− => (Text -> Maybe schema)
59− -- ^ Look up a schema.
60− -> (BaseURI -> schema -> BaseURI)
61− -- ^ Update scope (needed after moving deeper into nested schemas).
62− -> (VisitedSchemas -> Scope schema -> schema -> Value -> [err])
63− -- ^ Validate data.
64− -> VisitedSchemas
65− -> Scope schema
66− -> Ref
67− -> Value
68− -> Maybe (RefInvalid err)
69−refVal getRef updateScope val visited scope (Ref reference) x
70− | (mURI, mFragment) `elem` _unVisited visited =
71− Just (RefLoop reference visited (mURI, mFragment))
72− | otherwise = leftToMaybe $ do
73−
74− -- Get the referenced document
75−
76− (newScope, doc) <- first RefResolution
77− $ getDocument getRef updateScope scope mURI reference
78−
79− -- Get the correct subschema within that document.
80−
81− res <- case mFragment of
82− Nothing -> Right (newScope, doc)
83− Just fragment -> first RefPointerResolution
84− $ resolveFragment updateScope newScope fragment
85− let (finalScope, schema) = res
86−
87− -- Check if that schema is valid.
88−
89− let newVisited = VisitedSchemas [(_documentURI newScope, mFragment)]
90− <> visited
91− failures = val newVisited finalScope schema x
92− first (RefInvalid reference (toJSON schema))
93− . maybeToLeft ()
94− $ NE.nonEmpty failures
95− where
96− mURI :: Maybe Text
97− mFragment :: Maybe Text
98− (mURI, mFragment) = resolveReference (_currentBaseURI scope) reference
99−
100−getDocument
101− :: forall schema. (Text -> Maybe schema)
102− -> (BaseURI -> schema -> BaseURI)
103− -> Scope schema
104− -> Maybe Text
105− -> Text
106− -> Either Text (Scope schema, schema)
107− -- ^ 'Left' is the URI of the document we failed to resolve.
108−getDocument getRef updateScope scope mURI reference =
109− case mURI <* fst (resolveReference (BaseURI Nothing) reference) of
110− Nothing -> Right topOfThisDoc
111− Just uri ->
112− case getRef uri of
113− Nothing -> Left uri
114− Just s -> Right ( Scope s mURI (updateScope (BaseURI mURI) s)
115− , s
116− )
117− where
118− topOfThisDoc :: (Scope schema, schema)
119− topOfThisDoc =
120− ( scope { _currentBaseURI =
121− updateScope (BaseURI (_documentURI scope))
122− (_topLevelDocument scope)
123− }
124− , _topLevelDocument scope
125− )
126−
127−data JSONPointerError
128− = URLDecodingError UnicodeException
129− -- ^ Aspirationally internal.
130− | FormatError JP.FormatError
131− | ResolutionError JP.ResolutionError
132− | SubschemaDecodingError Text
133− -- ^ Aspirationally internal.
134− deriving (Eq, Show)
135−
136−resolveFragment
137− :: (FromJSON schema, ToJSON schema)
138− => (BaseURI -> schema -> BaseURI)
139− -> Scope schema
140− -> Text
141− -> Either JSONPointerError (Scope schema, schema)
142−resolveFragment updateScope scope fragment = do
143− urlDecoded <- first URLDecodingError
144− . decodeUtf8'
145− . urlDecode True
146− . encodeUtf8
147− $ fragment
148− JP.Pointer tokens <- first FormatError (JP.unescape urlDecoded)
149− let acc = (toJSON (_topLevelDocument scope), _currentBaseURI scope)
150− (schemaVal, base) <- foldM go acc tokens
151− schema <- first SubschemaDecodingError (fromJSONEither schemaVal)
152− pure (scope { _currentBaseURI = base }, schema)
153− where
154− -- We have to step through the document JSON Pointer token
155− -- by JSON Pointer token so that we can update the scope
156− -- based on each @"id"@ we encounter.
157− --
158− -- TODO: Do we need specialized code to skip @"id"@s such
159− -- as property keys that aren't meant to change scope?
160− -- Perhaps this should be added to the language agnostic
161− -- test suite as well.
162− --
163− -- In the meantime 'newBaseURIFromFragment' drops all keys
164− -- from JSON objects except "id", which at least prevents
165− -- SubschemaDecodingError in a situation where one of the
166− -- values we step through isn't a valid schema.
167− go :: (Value, BaseURI)
168− -> JP.Token
169− -> Either JSONPointerError (Value, BaseURI)
170− go (lastVal, baseURI) tok = do
171− v <- first ResolutionError (JP.resolveToken tok lastVal)
172− newBase <- newBaseURIFromFragment updateScope baseURI v
173− Right (v, newBase)
174−
175−-- | Update the 'BaseURI' (the store of the current "id" value)
176−-- after resolving one token of a JSON Pointer and stepping into
177−-- a new 'Value'.
178−newBaseURIFromFragment
179− :: FromJSON schema
180− => (BaseURI -> schema -> BaseURI)
181− -> BaseURI
182− -> Value
183− -> Either JSONPointerError BaseURI
184−newBaseURIFromFragment updateScope baseURI v =
185− case v of
186− Object hm -> do
187− let hmWithOnlyId = case HM.lookup idKey hm of
188− Nothing -> mempty
189− Just idVal -> HM.singleton idKey idVal
190− schema <- first SubschemaDecodingError (fromJSONEither (Object hmWithOnlyId))
191− Right (updateScope baseURI schema)
192− _ -> Right baseURI
193− where
194− idKey :: Text
195− idKey = "id"
196−
197−--------------------------------------------------
198−-- * enum
199−--------------------------------------------------
200−
201−-- | From the spec:
202−-- <http://json-schema.org/latest/json-schema-validation.html#anchor76>
203−--
204−-- > The value of this keyword MUST be an array.
205−-- > This array MUST have at least one element.
206−-- > Elements in the array MUST be unique.
207−--
208−-- NOTE: We don't enforce the uniqueness constraint in the haskell code,
209−-- but we do in the 'FromJSON' instance.
210−newtype EnumValidator
211− = EnumValidator { _unEnumValidator :: NonEmpty Value }
212− -- Given a choice, we'd prefer to enforce uniqueness through the type
213− -- system over having at least one element. To use a 'Set' though we'd
214− -- have to use 'OrdValue' here (there's no 'Ord' instance for plain Values)
215− -- and we'd rather not make users mess with 'OrdValue'.
216− deriving (Eq, Show)
217−
218−instance FromJSON EnumValidator where
219− parseJSON = withObject "EnumValidator" $ \o ->
220− EnumValidator <$> o .: "enum"
221−
222−instance Arbitrary EnumValidator where
223− arbitrary = do
224− xs <- (fmap.fmap) UT._unArbitraryValue arbitrary
225− case NE.nonEmpty (toUnique xs) of
226− Nothing -> EnumValidator . pure . UT._unArbitraryValue <$> arbitrary
227− Just ne -> pure (EnumValidator ne)
228− where
229− toUnique :: [Value] -> [Value]
230− toUnique = fmap UT._unOrdValue
231− . Set.toList
232− . Set.fromList
233− . fmap UT.OrdValue
234−
235−data EnumInvalid
236− = EnumInvalid EnumValidator Value
237− deriving (Eq, Show)
238−
239−enumVal :: EnumValidator -> Value -> Maybe EnumInvalid
240−enumVal a@(EnumValidator vs) x
241− | not (UT.allUniqueValues vs) = Nothing
242− | x `elem` vs = Nothing
243− | otherwise = Just $ EnumInvalid a x
244−
245−--------------------------------------------------
246−-- * type
247−--------------------------------------------------
248−
249−-- | This is separate from 'TypeValidator' so that 'TypeValidator' can
250−-- be used to write 'JSONSchema.Draft4.Schema.Schema' without
251−-- messing up the 'FromJSON' instance of that data type.
252−newtype TypeContext
253− = TypeContext { _unTypeContext :: TypeValidator }
254− deriving (Eq, Show)
255−
256−instance FromJSON TypeContext where
257− parseJSON = withObject "TypeContext" $ \o ->
258− TypeContext <$> o .: "type"
259−
260−data TypeValidator
261− = TypeValidatorString SchemaType
262− | TypeValidatorArray (Set SchemaType)
263− deriving (Eq, Show)
264−
265−instance Semigroup TypeValidator where
266− (<>) x y
267− | isEmpty x = x
268− | isEmpty y = y
269− | x == y = x
270− | otherwise = TypeValidatorArray (setFromTypeValidator x
271− `Set.union`
272− setFromTypeValidator y)
273− where
274− isEmpty :: TypeValidator -> Bool
275− isEmpty (TypeValidatorString _) = False
276− isEmpty (TypeValidatorArray ts) = Set.null ts
277−
278− stimes = stimesIdempotent
279−
280−instance FromJSON TypeValidator where
281− parseJSON v = fmap TypeValidatorString (parseJSON v)
282− <|> fmap TypeValidatorArray (parseJSON v)
283−
284−instance ToJSON TypeValidator where
285− toJSON (TypeValidatorString t) = toJSON t
286− toJSON (TypeValidatorArray ts) = toJSON ts
287−
288−instance Arbitrary TypeValidator where
289− arbitrary = oneof [ TypeValidatorString <$> arbitrary
290− , TypeValidatorArray <$> arbitrary
291− ]
292−
293−data SchemaType
294− = SchemaObject
295− | SchemaArray
296− | SchemaString
297− | SchemaNumber
298− | SchemaInteger
299− | SchemaBoolean
300− | SchemaNull
301− deriving (Eq, Ord, Show, Bounded, Enum, Generic)
302−
303−instance FromJSON SchemaType where
304− parseJSON = genericParseJSON
305− defaultOptions
306− { constructorTagModifier = fmap toLower . drop 6 }
307−
308−instance ToJSON SchemaType where
309− toJSON = genericToJSON
310− defaultOptions
311− { constructorTagModifier = fmap toLower . drop 6 }
312−
313−instance Arbitrary SchemaType where
314− arbitrary = arbitraryBoundedEnum
315−
316−data TypeValidatorInvalid
317− = TypeValidatorInvalid TypeValidator Value
318− deriving (Eq, Show)
319−
320−typeVal :: TypeContext -> Value -> Maybe TypeValidatorInvalid
321−typeVal (TypeContext tv) x
322− | Set.null matches = Just (TypeValidatorInvalid tv x)
323− | otherwise = Nothing
324− where
325− -- There can be more than one match because a 'Value' can be both a
326− -- @"number"@ and an @"integer"@.
327− matches :: Set SchemaType
328− matches = Set.intersection okTypes (setFromTypeValidator tv)
329−
330− okTypes :: Set SchemaType
331− okTypes =
332− case x of
333− Null -> Set.singleton SchemaNull
334− (Array _) -> Set.singleton SchemaArray
335− (Bool _) -> Set.singleton SchemaBoolean
336− (Object _) -> Set.singleton SchemaObject
337− (String _) -> Set.singleton SchemaString
338− (Number y) ->
339− if SCI.isInteger y
340− then Set.fromList [SchemaNumber, SchemaInteger]
341− else Set.singleton SchemaNumber
342−
343−-- | Internal.
344−setFromTypeValidator :: TypeValidator -> Set SchemaType
345−setFromTypeValidator (TypeValidatorString t) = Set.singleton t
346−setFromTypeValidator (TypeValidatorArray ts) = ts
347−
348−--------------------------------------------------
349−-- * allOf
350−--------------------------------------------------
351−
352−newtype AllOf schema
353− = AllOf { _unAllOf :: NonEmpty schema }
354− deriving (Eq, Show)
355−
356−instance FromJSON schema => FromJSON (AllOf schema) where
357− parseJSON = withObject "AllOf" $ \o ->
358− AllOf <$> o .: "allOf"
359−
360−newtype AllOfInvalid err
361− = AllOfInvalid (NonEmpty (JP.Index, NonEmpty err))
362− deriving (Eq, Show)
363−
364−allOfVal
365− :: forall err schema.
366− (schema -> Value -> [err])
367− -> AllOf schema
368− -> Value
369− -> Maybe (AllOfInvalid err)
370−allOfVal f (AllOf subSchemas) x = AllOfInvalid <$> NE.nonEmpty failures
371− where
372− perhapsFailures :: [(JP.Index, [err])]
373− perhapsFailures = zip (JP.Index <$> [0..])
374− (flip f x <$> NE.toList subSchemas)
375−
376− failures :: [(JP.Index, NonEmpty err)]
377− failures = mapMaybe (traverse NE.nonEmpty) perhapsFailures
378−
379−--------------------------------------------------
380−-- * anyOf
381−--------------------------------------------------
382−
383−newtype AnyOf schema
384− = AnyOf { _unAnyOf :: NonEmpty schema }
385− deriving (Eq, Show)
386−
387−instance FromJSON schema => FromJSON (AnyOf schema) where
388− parseJSON = withObject "AnyOf" $ \o ->
389− AnyOf <$> o .: "anyOf"
390−
391−newtype AnyOfInvalid err
392− = AnyOfInvalid (NonEmpty (JP.Index, NonEmpty err))
393− deriving (Eq, Show)
394−
395−anyOfVal
396− :: forall err schema.
397− (schema -> Value -> [err])
398− -> AnyOf schema
399− -> Value
400− -> Maybe (AnyOfInvalid err)
401−anyOfVal f (AnyOf subSchemas) x
402− | any (null . snd) perhapsFailures = Nothing
403− | otherwise = AnyOfInvalid <$> NE.nonEmpty failures
404− where
405− perhapsFailures :: [(JP.Index, [err])]
406− perhapsFailures = zip (JP.Index <$> [0..])
407− (flip f x <$> NE.toList subSchemas)
408−
409− failures :: [(JP.Index, NonEmpty err)]
410− failures = mapMaybe (traverse NE.nonEmpty) perhapsFailures
411−
412−--------------------------------------------------
413−-- * oneOf
414−--------------------------------------------------
415−
416−newtype OneOf schema
417− = OneOf { _unOneOf :: NonEmpty schema }
418− deriving (Eq, Show)
419−
420−instance FromJSON schema => FromJSON (OneOf schema) where
421− parseJSON = withObject "OneOf" $ \o ->
422− OneOf <$> o .: "oneOf"
423−
424−data OneOfInvalid err
425− = TooManySuccesses (NonEmpty (JP.Index, Value)) Value
426− -- ^ The NonEmpty lists contains tuples whose contents
427− -- are the index of a schema that validated the data
428− -- and the contents of that schema.
429− | NoSuccesses (NonEmpty (JP.Index, NonEmpty err)) Value
430− -- ^ The NonEmpty lists contains tuples whose contents
431− -- are the index of a schema that failed to validate the data
432− -- and the failures it produced.
433− deriving (Eq, Show)
434−
435−oneOfVal
436− :: forall err schema. ToJSON schema
437− => (schema -> Value -> [err])
438− -> OneOf schema
439− -> Value
440− -> Maybe (OneOfInvalid err)
441−oneOfVal f (OneOf (firstSubSchema :| otherSubSchemas)) x =
442− -- Producing the NonEmpty lists needed by the error constructors
443− -- is a little tricky. If we had a partition function like this
444− -- it might help:
445− -- @
446− -- (a -> Either b c) -> NonEmpty a -> Either (NonEmpty b, [c])
447− -- ([b], NonEmpty c)
448− -- @
449− case (firstSuccess, otherSuccesses) of
450− (Right _, Nothing) -> Nothing
451− (Right a, Just successes) -> Just (TooManySuccesses
452− (a NE.<| successes) x)
453− (Left e, Nothing) -> Just (NoSuccesses (e :| otherFailures) x)
454− (Left _, Just (_ :| [])) -> Nothing
455− (Left _, Just successes) -> Just (TooManySuccesses successes x)
456− where
457− firstSuccess :: Either (JP.Index, NonEmpty err) (JP.Index, Value)
458− firstSuccess =
459− case NE.nonEmpty (f firstSubSchema x) of
460− Nothing -> Right (JP.Index 0, toJSON firstSubSchema)
461− Just errs -> Left (JP.Index 0, errs)
462−
463− otherPerhapsFailures :: [(JP.Index, Value, [err])]
464− otherPerhapsFailures =
465− zipWith
466− (\index schema -> (index, toJSON schema, f schema x))
467− (JP.Index <$> [0..])
468− otherSubSchemas
469−
470− otherSuccesses :: Maybe (NonEmpty (JP.Index, Value))
471− otherSuccesses = NE.nonEmpty
472− $ mapMaybe (\(index,val,errs) ->
473− case errs of
474− [] -> Just (index,val)
475− _ -> Nothing
476− ) otherPerhapsFailures
477−
478− otherFailures :: [(JP.Index, NonEmpty err)]
479− otherFailures = mapMaybe (traverse NE.nonEmpty . mid) otherPerhapsFailures
480−
481− mid :: (a,b,c) -> (a,c)
482− mid (a,_,c) = (a,c)
483−
484−--------------------------------------------------
485−-- * not
486−--------------------------------------------------
487−
488−newtype NotValidator schema
489− = NotValidator { _unNotValidator :: schema }
490− deriving (Eq, Show)
491−
492−instance FromJSON schema => FromJSON (NotValidator schema) where
493− parseJSON = withObject "NotValidator" $ \o ->
494− NotValidator <$> o .: "not"
495−
496−data NotValidatorInvalid
497− = NotValidatorInvalid Value Value
498− deriving (Eq, Show)
499−
500−notVal
501− :: ToJSON schema =>
502− (schema -> Value -> [err])
503− -> NotValidator schema
504− -> Value
505− -> Maybe NotValidatorInvalid
506−notVal f (NotValidator schema) x =
507− case f schema x of
508− [] -> Just (NotValidatorInvalid (toJSON schema) x)
509− _ -> Nothing
src/JSONSchema/Validator/Draft4/Array.hsdeleted−225
@@ -1,225 +0,0 @@
1−module JSONSchema.Validator.Draft4.Array where
2−
3−import Import
4−
5−import qualified Data.List.NonEmpty as NE
6−import qualified Data.Vector as V
7−import qualified JSONPointer as JP
8−
9−import JSONSchema.Validator.Utils (allUniqueValues)
10−
11−--------------------------------------------------
12−-- * maxItems
13−--------------------------------------------------
14−
15−newtype MaxItems
16− = MaxItems { _unMaxItems :: Int }
17− deriving (Eq, Show)
18−
19−instance FromJSON MaxItems where
20− parseJSON = withObject "MaxItems" $ \o ->
21− MaxItems <$> o .: "maxItems"
22−
23−data MaxItemsInvalid
24− = MaxItemsInvalid MaxItems (Vector Value)
25− deriving (Eq, Show)
26−
27−-- | The spec requires @"maxItems"@ to be non-negative.
28−maxItemsVal :: MaxItems -> Vector Value -> Maybe MaxItemsInvalid
29−maxItemsVal a@(MaxItems n) xs
30− | n < 0 = Nothing
31− | V.length xs > n = Just (MaxItemsInvalid a xs)
32− | otherwise = Nothing
33−
34−--------------------------------------------------
35−-- * minItems
36−--------------------------------------------------
37−
38−newtype MinItems
39− = MinItems { _unMinItems :: Int }
40− deriving (Eq, Show)
41−
42−instance FromJSON MinItems where
43− parseJSON = withObject "MinItems" $ \o ->
44− MinItems <$> o .: "minItems"
45−
46−data MinItemsInvalid
47− = MinItemsInvalid MinItems (Vector Value)
48− deriving (Eq, Show)
49−
50−-- | The spec requires @"minItems"@ to be non-negative.
51−minItemsVal :: MinItems -> Vector Value -> Maybe MinItemsInvalid
52−minItemsVal a@(MinItems n) xs
53− | n < 0 = Nothing
54− | V.length xs < n = Just (MinItemsInvalid a xs)
55− | otherwise = Nothing
56−
57−--------------------------------------------------
58−-- * uniqueItems
59−--------------------------------------------------
60−
61−newtype UniqueItems
62− = UniqueItems { _unUniqueItems :: Bool }
63− deriving (Eq, Show)
64−
65−instance FromJSON UniqueItems where
66− parseJSON = withObject "UniqueItems" $ \o ->
67− UniqueItems <$> o .: "uniqueItems"
68−
69−newtype UniqueItemsInvalid
70− = UniqueItemsInvalid (Vector Value)
71− deriving (Eq, Show)
72−
73−uniqueItemsVal :: UniqueItems -> Vector Value -> Maybe UniqueItemsInvalid
74−uniqueItemsVal (UniqueItems True) xs
75− | allUniqueValues xs = Nothing
76− | otherwise = Just (UniqueItemsInvalid xs)
77−uniqueItemsVal (UniqueItems False) _ = Nothing
78−
79−--------------------------------------------------
80−-- * items
81−--------------------------------------------------
82−
83−data ItemsRelated schema = ItemsRelated
84− { _irItems :: Maybe (Items schema)
85− , _irAdditional :: Maybe (AdditionalItems schema)
86− } deriving (Eq, Show)
87−
88−instance FromJSON schema => FromJSON (ItemsRelated schema) where
89− parseJSON = withObject "ItemsRelated" $ \o -> ItemsRelated
90− <$> o .:! "items"
91− <*> o .:! "additionalItems"
92−
93−emptyItems :: ItemsRelated schema
94−emptyItems = ItemsRelated
95− { _irItems = Nothing
96− , _irAdditional = Nothing
97− }
98−
99−data Items schema
100− = ItemsObject schema
101− | ItemsArray [schema]
102− deriving (Eq, Show)
103−
104−instance FromJSON schema => FromJSON (Items schema) where
105− parseJSON v = fmap ItemsObject (parseJSON v)
106− <|> fmap ItemsArray (parseJSON v)
107−
108−instance ToJSON schema => ToJSON (Items schema) where
109− toJSON (ItemsObject hm) = toJSON hm
110− toJSON (ItemsArray schemas) = toJSON schemas
111−
112−instance Arbitrary schema => Arbitrary (Items schema) where
113− arbitrary = oneof [ ItemsObject <$> arbitrary
114− , ItemsArray <$> arbitrary
115− ]
116−
117−data ItemsRelatedInvalid err
118− = IRInvalidItems (ItemsInvalid err)
119− | IRInvalidAdditional (AdditionalItemsInvalid err)
120− deriving (Eq, Show)
121−
122−data ItemsInvalid err
123− = ItemsObjectInvalid (NonEmpty (JP.Index, NonEmpty err))
124− | ItemsArrayInvalid (NonEmpty (JP.Index, NonEmpty err))
125− deriving (Eq, Show)
126−
127−-- | @"additionalItems"@ only matters if @"items"@ exists
128−-- and is a JSON Array.
129−itemsRelatedVal
130− :: forall err schema.
131− (schema -> Value -> [err])
132− -> ItemsRelated schema
133− -> Vector Value
134− -> [ItemsRelatedInvalid err] -- NOTE: 'Data.These' would help here.
135−itemsRelatedVal f a xs =
136− let (itemsFailure, remaining) = case _irItems a of
137− Nothing -> (Nothing, mempty)
138− Just b -> itemsVal f b xs
139− additionalFailure = (\b -> additionalItemsVal f b remaining)
140− =<< _irAdditional a
141− in catMaybes [ IRInvalidItems <$> itemsFailure
142− , IRInvalidAdditional <$> additionalFailure
143− ]
144−
145−-- | Internal.
146−--
147−-- This is because 'itemsRelated' handles @"items"@ validation.
148−itemsVal
149− :: forall err schema.
150− (schema -> Value -> [err])
151− -> Items schema
152− -> Vector Value
153− -> (Maybe (ItemsInvalid err), [(JP.Index, Value)])
154− -- ^ The second item in the tuple is the elements of the original
155− -- JSON Array still remaining to be checked by @"additionalItems"@.
156−itemsVal f a xs =
157− case a of
158− ItemsObject subSchema ->
159− case NE.nonEmpty (mapMaybe (validateElem subSchema) indexed) of
160− Nothing -> (Nothing, mempty)
161− Just errs -> (Just (ItemsObjectInvalid errs), mempty)
162− ItemsArray subSchemas ->
163− let remaining = drop (length subSchemas) indexed
164− res = catMaybes (zipWith validateElem subSchemas indexed)
165− in case NE.nonEmpty res of
166− Nothing -> (Nothing, remaining)
167− Just errs -> (Just (ItemsArrayInvalid errs), remaining)
168− where
169− indexed :: [(JP.Index, Value)]
170− indexed = zip (JP.Index <$> [0..]) (V.toList xs)
171−
172− validateElem
173− :: schema
174− -> (JP.Index, Value)
175− -> Maybe (JP.Index, NonEmpty err)
176− validateElem schema (index,x) =
177− (\v -> (index, v)) <$> NE.nonEmpty (f schema x)
178−
179−--------------------------------------------------
180−-- * additionalItems
181−--------------------------------------------------
182−
183−data AdditionalItems schema
184− = AdditionalBool Bool
185− | AdditionalObject schema
186− deriving (Eq, Show)
187−
188−instance FromJSON schema => FromJSON (AdditionalItems schema) where
189− parseJSON v = fmap AdditionalBool (parseJSON v)
190− <|> fmap AdditionalObject (parseJSON v)
191−
192−instance ToJSON schema => ToJSON (AdditionalItems schema) where
193− toJSON (AdditionalBool b) = toJSON b
194− toJSON (AdditionalObject hm) = toJSON hm
195−
196−instance Arbitrary schema => Arbitrary (AdditionalItems schema) where
197− arbitrary = oneof [ AdditionalBool <$> arbitrary
198− , AdditionalObject <$> arbitrary
199− ]
200−
201−data AdditionalItemsInvalid err
202− = AdditionalItemsBoolInvalid (NonEmpty (JP.Index, Value))
203− | AdditionalItemsObjectInvalid (NonEmpty (JP.Index, NonEmpty err))
204− deriving (Eq, Show)
205−
206−-- | Internal.
207−--
208−-- This is because 'itemsRelated' handles @"additionalItems"@ validation.
209−additionalItemsVal
210− :: forall err schema.
211− (schema -> Value -> [err])
212− -> AdditionalItems schema
213− -> [(JP.Index, Value)]
214− -- ^ The elements remaining to validate after the ones covered by
215− -- @"items"@ have been removed.
216− -> Maybe (AdditionalItemsInvalid err)
217−additionalItemsVal _ (AdditionalBool True) _ = Nothing
218−additionalItemsVal _ (AdditionalBool False) xs =
219− AdditionalItemsBoolInvalid <$> NE.nonEmpty xs
220−additionalItemsVal f (AdditionalObject subSchema) xs =
221− let res = mapMaybe
222− (\(index,x) -> (\v -> (index, v))
223− <$> NE.nonEmpty (f subSchema x))
224− xs
225− in AdditionalItemsObjectInvalid <$> NE.nonEmpty res
src/JSONSchema/Validator/Draft4/Number.hsdeleted−83
@@ -1,83 +0,0 @@
1−module JSONSchema.Validator.Draft4.Number where
2−
3−import Import
4−
5−import Data.Fixed (mod')
6−import Data.Scientific (Scientific)
7−
8−--------------------------------------------------
9−-- * multipleOf
10−--------------------------------------------------
11−
12−newtype MultipleOf
13− = MultipleOf { _unMultipleOf :: Scientific }
14− deriving (Eq, Show)
15−
16−instance FromJSON MultipleOf where
17− parseJSON = withObject "MultipleOf" $ \o ->
18− MultipleOf <$> o .: "multipleOf"
19−
20−data MultipleOfInvalid
21− = MultipleOfInvalid MultipleOf Scientific
22− deriving (Eq, Show)
23−
24−-- | The spec requires @"multipleOf"@ to be positive.
25−multipleOfVal :: MultipleOf -> Scientific -> Maybe MultipleOfInvalid
26−multipleOfVal a@(MultipleOf n) x
27− | n <= 0 = Nothing
28− | x `mod'` n /= 0 = Just (MultipleOfInvalid a x)
29− | otherwise = Nothing
30−
31−--------------------------------------------------
32−-- * maximum
33−--------------------------------------------------
34−
35−data Maximum = Maximum
36− { _maximumExclusive :: Bool
37− , _maximumValue :: Scientific
38− } deriving (Eq, Show)
39−
40−instance FromJSON Maximum where
41− parseJSON = withObject "Maximum" $ \o -> Maximum
42− <$> o .:! "exclusiveMaximum" .!= False
43− <*> o .: "maximum"
44−
45−data MaximumInvalid
46− = MaximumInvalid Maximum Scientific
47− deriving (Eq, Show)
48−
49−maximumVal
50− :: Maximum
51− -> Scientific
52− -> Maybe MaximumInvalid
53−maximumVal a@(Maximum exclusive n) x
54− | exclusive && x >= n = Just (MaximumInvalid a x)
55− | x > n = Just (MaximumInvalid a x)
56− | otherwise = Nothing
57−
58−--------------------------------------------------
59−-- * minimum
60−--------------------------------------------------
61−
62−data Minimum = Minimum
63− { _minimumExclusive :: Bool
64− , _minimumValue :: Scientific
65− } deriving (Eq, Show)
66−
67−instance FromJSON Minimum where
68− parseJSON = withObject "Minimum" $ \o -> Minimum
69− <$> o .:! "exclusiveMinimum" .!= False
70− <*> o .: "minimum"
71−
72−data MinimumInvalid
73− = MinimumInvalid Minimum Scientific
74− deriving (Eq, Show)
75−
76−minimumVal
77− :: Minimum
78− -> Scientific
79− -> Maybe MinimumInvalid
80−minimumVal a@(Minimum exclusive n) x
81− | exclusive && x <= n = Just (MinimumInvalid a x)
82− | x < n = Just (MinimumInvalid a x)
83− | otherwise = Nothing
src/JSONSchema/Validator/Draft4/Object.hsdeleted−182
@@ -1,182 +0,0 @@
1−module JSONSchema.Validator.Draft4.Object
2− ( module JSONSchema.Validator.Draft4.Object
3− , module JSONSchema.Validator.Draft4.Object.Properties
4− ) where
5−
6−import Import
7−
8−import qualified Data.HashMap.Strict as HM
9−import qualified Data.List.NonEmpty as NE
10−import Data.Set (Set)
11−import qualified Data.Set as Set
12−import qualified Data.Text as T
13−
14−import JSONSchema.Validator.Draft4.Object.Properties
15−import JSONSchema.Validator.Utils
16−
17−--------------------------------------------------
18−-- * maxProperties
19−--------------------------------------------------
20−
21−newtype MaxProperties
22− = MaxProperties { _unMaxProperties :: Int }
23− deriving (Eq, Show)
24−
25−instance FromJSON MaxProperties where
26− parseJSON = withObject "MaxProperties" $ \o ->
27− MaxProperties <$> o .: "maxProperties"
28−
29−data MaxPropertiesInvalid
30− = MaxPropertiesInvalid MaxProperties (HashMap Text Value)
31− deriving (Eq, Show)
32−
33−-- | The spec requires @"maxProperties"@ to be non-negative.
34−maxPropertiesVal
35− :: MaxProperties
36− -> HashMap Text Value
37− -> Maybe MaxPropertiesInvalid
38−maxPropertiesVal a@(MaxProperties n) x
39− | n < 0 = Nothing
40− | HM.size x > n = Just (MaxPropertiesInvalid a x)
41− | otherwise = Nothing
42−
43−--------------------------------------------------
44−-- * minProperties
45−--------------------------------------------------
46−
47−newtype MinProperties
48− = MinProperties { _unMinProperties :: Int }
49− deriving (Eq, Show)
50−
51−instance FromJSON MinProperties where
52− parseJSON = withObject "MinProperties" $ \o ->
53− MinProperties <$> o .: "minProperties"
54−
55−data MinPropertiesInvalid
56− = MinPropertiesInvalid MinProperties (HashMap Text Value)
57− deriving (Eq, Show)
58−
59−-- | The spec requires @"minProperties"@ to be non-negative.
60−minPropertiesVal
61− :: MinProperties
62− -> HashMap Text Value
63− -> Maybe MinPropertiesInvalid
64−minPropertiesVal a@(MinProperties n) x
65− | n < 0 = Nothing
66− | HM.size x < n = Just (MinPropertiesInvalid a x)
67− | otherwise = Nothing
68−
69−--------------------------------------------------
70−-- * required
71−--------------------------------------------------
72−
73−-- | From the spec:
74−--
75−-- > The value of this keyword MUST be an array.
76−-- > This array MUST have at least one element.
77−-- > Elements of this array MUST be strings, and MUST be unique.
78−newtype Required
79− = Required { _unRequired :: Set Text }
80− deriving (Eq, Show)
81−
82−instance FromJSON Required where
83− parseJSON = withObject "Required" $ \o ->
84− Required <$> o .: "required"
85−
86−instance Arbitrary Required where
87− arbitrary = do
88− x <- arbitraryText -- Guarantee at least one element.
89− xs <- (fmap.fmap) T.pack arbitrary
90− pure . Required . Set.fromList $ x:xs
91−
92−data RequiredInvalid
93− = RequiredInvalid Required (Set Text) (HashMap Text Value)
94− deriving (Eq, Show)
95−
96−requiredVal :: Required -> HashMap Text Value -> Maybe RequiredInvalid
97−requiredVal r@(Required ts) x
98− | Set.null ts = Nothing
99− | Set.null leftovers = Nothing
100− | otherwise = Just (RequiredInvalid r leftovers x)
101− where
102− leftovers :: Set Text
103− leftovers =
104− Set.difference -- Items of the first set not in the second.
105− ts
106− (Set.fromList (HM.keys x))
107−
108−--------------------------------------------------
109−-- * dependencies
110−--------------------------------------------------
111−
112−newtype DependenciesValidator schema
113− = DependenciesValidator
114− { _unDependenciesValidator :: HashMap Text (Dependency schema) }
115− deriving (Eq, Show)
116−
117−instance FromJSON schema => FromJSON (DependenciesValidator schema) where
118− parseJSON = withObject "DependenciesValidator" $ \o ->
119− DependenciesValidator <$> o .: "dependencies"
120−
121−data Dependency schema
122− = SchemaDependency schema
123− | PropertyDependency (Set Text)
124− deriving (Eq, Show)
125−
126−instance FromJSON schema => FromJSON (Dependency schema) where
127− parseJSON v = fmap SchemaDependency (parseJSON v)
128− <|> fmap PropertyDependency (parseJSON v)
129−
130−instance ToJSON schema => ToJSON (Dependency schema) where
131− toJSON (SchemaDependency schema) = toJSON schema
132− toJSON (PropertyDependency ts) = toJSON ts
133−
134−instance Arbitrary schema => Arbitrary (Dependency schema) where
135− arbitrary = oneof [ SchemaDependency <$> arbitrary
136− , PropertyDependency <$> arbitrarySetOfText
137− ]
138−
139−data DependencyMemberInvalid err
140− = SchemaDepInvalid (NonEmpty err)
141− | PropertyDepInvalid (Set Text) (HashMap Text Value)
142− deriving (Eq, Show)
143−
144−newtype DependenciesInvalid err
145− = DependenciesInvalid (HashMap Text (DependencyMemberInvalid err))
146− deriving (Eq, Show)
147−
148−-- | From the spec:
149−-- <http://json-schema.org/latest/json-schema-validation.html#anchor70>
150−--
151−-- > This keyword's value MUST be an object.
152−-- > Each value of this object MUST be either an object or an array.
153−-- >
154−-- > If the value is an object, it MUST be a valid JSON Schema.
155−-- > This is called a schema dependency.
156−-- >
157−-- > If the value is an array, it MUST have at least one element.
158−-- > Each element MUST be a string, and elements in the array MUST be unique.
159−-- > This is called a property dependency.
160−dependenciesVal
161− :: forall err schema.
162− (schema -> Value -> [err])
163− -> DependenciesValidator schema
164− -> HashMap Text Value
165− -> Maybe (DependenciesInvalid err)
166−dependenciesVal f (DependenciesValidator hm) x =
167− let res = HM.mapMaybeWithKey g hm
168− in if HM.null res
169− then Nothing
170− else Just (DependenciesInvalid res)
171− where
172− g :: Text -> Dependency schema -> Maybe (DependencyMemberInvalid err)
173− g k (SchemaDependency schema)
174− | HM.member k x = SchemaDepInvalid
175− <$> NE.nonEmpty (f schema (Object x))
176− | otherwise = Nothing
177− g k (PropertyDependency ts)
178− | HM.member k x && not allPresent = Just (PropertyDepInvalid ts x)
179− | otherwise = Nothing
180− where
181− allPresent :: Bool
182− allPresent = all (`HM.member` x) ts
src/JSONSchema/Validator/Draft4/Object/Properties.hsdeleted−209
@@ -1,209 +0,0 @@
1−module JSONSchema.Validator.Draft4.Object.Properties where
2−
3−import Import
4−
5−import qualified Data.Hashable as HA
6−import qualified Data.HashMap.Strict as HM
7−import qualified Data.List.NonEmpty as NE
8−import Data.Text.Encoding (encodeUtf8)
9−import qualified JSONPointer as JP
10−import qualified Text.Regex.PCRE.Heavy as RE
11−
12−data PropertiesRelated schema = PropertiesRelated
13− { _propProperties :: Maybe (HashMap Text schema)
14− -- ^ 'Maybe' is used to distinguish whether the key is present or not.
15− , _propPattern :: Maybe (HashMap Text schema)
16− , _propAdditional :: Maybe (AdditionalProperties schema)
17− } deriving (Eq, Show)
18−
19−instance FromJSON schema => FromJSON (PropertiesRelated schema) where
20− parseJSON = withObject "PropertiesRelated" $ \o -> PropertiesRelated
21− <$> o .:! "properties"
22− <*> o .:! "patternProperties"
23− <*> o .:! "additionalProperties"
24−
25−emptyProperties :: PropertiesRelated schema
26−emptyProperties = PropertiesRelated
27− { _propProperties = Nothing
28− , _propPattern = Nothing
29− , _propAdditional = Nothing
30− }
31−
32−data AdditionalProperties schema
33− = AdditionalPropertiesBool Bool
34− | AdditionalPropertiesObject schema
35− deriving (Eq, Show)
36−
37−instance FromJSON schema => FromJSON (AdditionalProperties schema) where
38− parseJSON v = fmap AdditionalPropertiesBool (parseJSON v)
39− <|> fmap AdditionalPropertiesObject (parseJSON v)
40−
41−instance ToJSON schema => ToJSON (AdditionalProperties schema) where
42− toJSON (AdditionalPropertiesBool b) = toJSON b
43− toJSON (AdditionalPropertiesObject hm) = toJSON hm
44−
45−instance Arbitrary schema => Arbitrary (AdditionalProperties schema) where
46− arbitrary = oneof [ AdditionalPropertiesBool <$> arbitrary
47− , AdditionalPropertiesObject <$> arbitrary
48− ]
49−
50−-- | A glorified @type@ alias.
51−newtype Regex
52− = Regex { _unRegex :: Text }
53− deriving (Eq, Show, Generic)
54−
55−instance HA.Hashable Regex
56−
57−-- NOTE: We'd like to enforce that at least one error exists here.
58−data PropertiesRelatedInvalid err = PropertiesRelatedInvalid
59− { _prInvalidProperties :: HashMap Text [err]
60− , _prInvalidPattern :: HashMap (Regex, JP.Key) [err]
61− , _prInvalidAdditional :: Maybe (APInvalid err)
62− } deriving (Eq, Show)
63−
64−data APInvalid err
65− = APBoolInvalid (HashMap Text Value)
66− | APObjectInvalid (HashMap Text (NonEmpty err))
67− deriving (Eq, Show)
68−
69−-- | First @"properties"@ and @"patternProperties"@ are run simultaneously
70−-- on the data, then @"additionalProperties"@ is run on the remainder.
71−propertiesRelatedVal
72− :: forall err schema.
73− (schema -> Value -> [err])
74− -> PropertiesRelated schema
75− -> HashMap Text Value
76− -> Maybe (PropertiesRelatedInvalid err)
77−propertiesRelatedVal f props x
78− | all null (HM.elems propFailures)
79− && all null (HM.elems patFailures)
80− && isNothing addFailures = Nothing
81− | otherwise =
82− Just PropertiesRelatedInvalid
83− { _prInvalidProperties = propFailures
84− , _prInvalidPattern = patFailures
85− , _prInvalidAdditional = addFailures
86− }
87− where
88− propertiesHm :: HashMap Text schema
89− propertiesHm = fromMaybe mempty (_propProperties props)
90−
91− patHm :: HashMap Text schema
92− patHm = fromMaybe mempty (_propPattern props)
93−
94− propAndUnmatched :: (HashMap Text [err], Remaining)
95− propAndUnmatched = ( HM.intersectionWith f propertiesHm x
96− , Remaining (HM.difference x propertiesHm)
97− )
98−
99− (propFailures, propRemaining) = propAndUnmatched
100−
101− patAndUnmatched :: (HashMap (Regex, JP.Key) [err], Remaining)
102− patAndUnmatched = patternAndUnmatched f patHm x
103−
104− (patFailures, patRemaining) = patAndUnmatched
105−
106− finalRemaining :: Remaining
107− finalRemaining = Remaining (HM.intersection (_unRemaining patRemaining)
108− (_unRemaining propRemaining))
109−
110− addFailures :: Maybe (APInvalid err)
111− addFailures = (\addProp -> additionalProperties f addProp finalRemaining)
112− =<< _propAdditional props
113−
114−-- | Internal.
115−newtype Remaining
116− = Remaining { _unRemaining :: HashMap Text Value }
117−
118−-- | Internal.
119−patternAndUnmatched
120− :: forall err schema.
121− (schema -> Value -> [err])
122− -> HashMap Text schema
123− -> HashMap Text Value
124− -> (HashMap (Regex, JP.Key) [err], Remaining)
125−patternAndUnmatched f patPropertiesHm x =
126− (HM.foldlWithKey' runMatches mempty perhapsMatches, remaining)
127− where
128− -- @[(Regex, schema)]@ will have one item per match.
129− perhapsMatches :: HashMap Text ([(Regex, schema)], Value)
130− perhapsMatches =
131− HM.foldlWithKey' (matchingSchemas patPropertiesHm) mempty x
132− where
133− matchingSchemas
134− :: HashMap Text schema
135− -> HashMap Text ([(Regex, schema)], Value)
136− -> Text
137− -> Value
138− -> HashMap Text ([(Regex, schema)], Value)
139− matchingSchemas subSchemas acc k v =
140− HM.insert k
141− (HM.foldlWithKey' (checkKey k) mempty subSchemas, v)
142− acc
143−
144− checkKey
145− :: Text
146− -> [(Regex, schema)]
147− -> Text
148− -> schema
149− -> [(Regex, schema)]
150− checkKey k acc r subSchema =
151− case RE.compileM (encodeUtf8 r) mempty of
152− Left _ -> acc
153− Right re -> if k RE.=~ re
154− then (Regex r, subSchema) : acc
155− else acc
156−
157− runMatches
158− :: HashMap (Regex, JP.Key) [err]
159− -> Text
160− -> ([(Regex, schema)], Value)
161− -> HashMap (Regex, JP.Key) [err]
162− runMatches acc k (matches,v) =
163− foldr runMatch acc matches
164− where
165− runMatch
166− :: (Regex, schema)
167− -> HashMap (Regex, JP.Key) [err]
168− -> HashMap (Regex, JP.Key) [err]
169− runMatch (r,schema) = HM.insert (r, JP.Key k) (f schema v)
170−
171− remaining :: Remaining
172− remaining = Remaining . fmap snd . HM.filter (null . fst) $ perhapsMatches
173−
174−-- Internal.
175−additionalProperties
176− :: forall err schema.
177− (schema -> Value -> [err])
178− -> AdditionalProperties schema
179− -> Remaining
180− -> Maybe (APInvalid err)
181−additionalProperties f a x =
182− case a of
183− AdditionalPropertiesBool b ->
184− APBoolInvalid <$> additionalPropertiesBool b x
185− AdditionalPropertiesObject b ->
186− APObjectInvalid <$> additionalPropertiesObject f b x
187−
188−-- | Internal.
189−additionalPropertiesBool
190− :: Bool
191− -> Remaining
192− -> Maybe (HashMap Text Value)
193−additionalPropertiesBool True _ = Nothing
194−additionalPropertiesBool False (Remaining x)
195− | HM.size x > 0 = Just x
196− | otherwise = Nothing
197−
198−-- | Internal.
199−additionalPropertiesObject
200− :: forall err schema.
201− (schema -> Value -> [err])
202− -> schema
203− -> Remaining
204− -> Maybe (HashMap Text (NonEmpty err))
205−additionalPropertiesObject f schema (Remaining x) =
206− let errs = HM.mapMaybe (NE.nonEmpty . f schema) x
207− in if HM.null errs
208− then Nothing
209− else Just errs
src/JSONSchema/Validator/Draft4/String.hsdeleted−78
@@ -1,78 +0,0 @@
1−module JSONSchema.Validator.Draft4.String where
2−
3−import Import
4−
5−import qualified Data.Text as T
6−import Data.Text.Encoding (encodeUtf8)
7−import qualified Text.Regex.PCRE.Heavy as RE
8−
9−--------------------------------------------------
10−-- * maxLength
11−--------------------------------------------------
12−
13−newtype MaxLength
14− = MaxLength { _unMaxLength :: Int }
15− deriving (Eq, Show)
16−
17−instance FromJSON MaxLength where
18− parseJSON = withObject "MaxLength" $ \o ->
19− MaxLength <$> o .: "maxLength"
20−
21−data MaxLengthInvalid
22− = MaxLengthInvalid MaxLength Text
23− deriving (Eq, Show)
24−
25−-- | The spec requires @"maxLength"@ to be non-negative.
26−maxLengthVal :: MaxLength -> Text -> Maybe MaxLengthInvalid
27−maxLengthVal a@(MaxLength n) x
28− | n <= 0 = Nothing
29− | T.length x > n = Just (MaxLengthInvalid a x)
30− | otherwise = Nothing
31−
32−--------------------------------------------------
33−-- * minLength
34−--------------------------------------------------
35−
36−newtype MinLength
37− = MinLength { _unMinLength :: Int }
38− deriving (Eq, Show)
39−
40−instance FromJSON MinLength where
41− parseJSON = withObject "MinLength" $ \o ->
42− MinLength <$> o .: "minLength"
43−
44−data MinLengthInvalid
45− = MinLengthInvalid MinLength Text
46− deriving (Eq, Show)
47−
48−-- | The spec requires @"minLength"@ to be non-negative.
49−minLengthVal :: MinLength -> Text -> Maybe MinLengthInvalid
50−minLengthVal a@(MinLength n) x
51− | n <= 0 = Nothing
52− | T.length x < n = Just (MinLengthInvalid a x)
53− | otherwise = Nothing
54−
55−--------------------------------------------------
56−-- * pattern
57−--------------------------------------------------
58−
59−newtype PatternValidator
60− = PatternValidator { _unPatternValidator :: Text }
61− deriving (Eq, Show)
62−
63−instance FromJSON PatternValidator where
64− parseJSON = withObject "PatternValidator" $ \o ->
65− PatternValidator <$> o .: "pattern"
66−
67−data PatternInvalid
68− = PatternNotRegex -- TODO: let these pass successfully?
69− | PatternInvalid PatternValidator Text
70− deriving (Eq, Show)
71−
72−patternVal :: PatternValidator -> Text -> Maybe PatternInvalid
73−patternVal a@(PatternValidator t) x =
74− case RE.compileM (encodeUtf8 t) mempty of
75− Left _ -> Just PatternNotRegex
76− Right re -> if x RE.=~ re
77− then Nothing
78− else Just (PatternInvalid a x)
src/JSONSchema/Validator/Reference.hsdeleted−71
@@ -1,71 +0,0 @@
1−-- | JSON Reference is described here:
2−-- <http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03>
3−--
4−-- And is extended for JSON Schema here:
5−-- <http://json-schema.org/latest/json-schema-core.html#anchor26>
6−module JSONSchema.Validator.Reference where
7−
8−import Import
9−
10−import qualified Data.Text as T
11−import System.FilePath (dropFileName, (</>))
12−
13−data Scope schema = Scope
14− { _topLevelDocument :: schema
15− , _documentURI :: Maybe Text
16− , _currentBaseURI :: BaseURI
17− } deriving (Eq, Show)
18−
19−newtype BaseURI
20− = BaseURI { _unBaseURI :: Maybe Text }
21− deriving (Eq, Show)
22−
23−-- | TODO: no `type`s.
24−type URIAndFragment = (Maybe Text, Maybe Text)
25−
26−updateResolutionScope :: BaseURI -> Maybe Text -> BaseURI
27−updateResolutionScope base idKeyword =
28− case idKeyword of
29− Just t -> BaseURI . fst . baseAndFragment $ resolveScopeAgainst base t
30− Nothing -> base
31−
32−resolveReference :: BaseURI -> Text -> URIAndFragment
33−resolveReference base t = baseAndFragment (resolveScopeAgainst base t)
34−
35−--------------------------------------------------
36−-- * Helpers
37−--------------------------------------------------
38−
39−isRemoteReference :: Text -> Bool
40−isRemoteReference = T.isInfixOf "://"
41−
42−baseAndFragment :: Text -> URIAndFragment
43−baseAndFragment = f . T.splitOn "#"
44− where
45− f :: [Text] -> URIAndFragment
46− f [x] = (g x, Nothing)
47− f [x,y] = (g x, g y)
48− f _ = (Nothing, Nothing)
49−
50− g "" = Nothing
51− g x = Just x
52−
53−resolveScopeAgainst :: BaseURI -> Text -> Text
54−resolveScopeAgainst (BaseURI Nothing) t = t
55−resolveScopeAgainst (BaseURI (Just base)) t
56− | isRemoteReference t = t
57− | otherwise = smartAppend
58− where
59− -- There shouldn't be a fragment at the end of a scope URI,
60− -- but just in case a user leaves one in we want to be sure
61− -- to cut it off before appending.
62− smartAppend :: Text
63− smartAppend =
64− case baseAndFragment base of
65− (Just uri,_) ->
66− case T.unpack t of
67− -- We want "/foo" and "#/bar" to combine into
68− -- "/foo#/bar" not "/foo/#/bar".
69− '#':_ -> base <> t
70− _ -> T.pack (dropFileName (T.unpack uri) </> T.unpack t)
71− _ -> t
src/JSONSchema/Validator/Types.hsdeleted−22
@@ -1,22 +0,0 @@
1−module JSONSchema.Validator.Types where
2−
3−import Import
4−
5−import Data.Profunctor (Profunctor(..))
6−
7−data Validator schema val err = Validator
8− { _embedded :: val -> ([schema], [schema])
9− -- ^ The first list is embedded schemas that validate the same piece
10− -- of data this schema validates (such as schemas embedded in 'allOf').
11− -- The second is embedded schemas that validate a subset of that data
12− -- (such as the schemas embedded in 'items').
13− --
14− -- This is done to allow static detection of loops, though this isn't
15− -- implemented yet (though the Draft4 code does do live loop detection
16− -- during validation).
17− , _validate :: val -> Value -> [err]
18− } deriving Functor
19−
20−instance Profunctor (Validator schema) where
21− lmap f (Validator a b) = Validator (lmap f a) (lmap f b)
22− rmap = fmap
src/JSONSchema/Validator/Utils.hsdeleted−119
@@ -1,119 +0,0 @@
1−module JSONSchema.Validator.Utils where
2−
3−import Import
4−
5−import Control.Monad (fail)
6−import qualified Data.HashMap.Strict as HM
7−import qualified Data.List.NonEmpty as NE
8−import Data.Scientific (Scientific, fromFloatDigits)
9−import Data.Set (Set)
10−import qualified Data.Set as S
11−import qualified Data.Text as T
12−import qualified Data.Vector as V
13−
14−--------------------------------------------------
15−-- * QuickCheck
16−--------------------------------------------------
17−
18−arbitraryText :: Gen Text
19−arbitraryText = T.pack <$> arbitrary
20−
21−arbitraryScientific :: Gen Scientific
22−arbitraryScientific = (fromFloatDigits :: Double -> Scientific) <$> arbitrary
23−
24−arbitraryPositiveScientific :: Gen Scientific
25−arbitraryPositiveScientific = (fromFloatDigits :: Double -> Scientific)
26− . getPositive
27− <$> arbitrary
28−
29−newtype ArbitraryValue
30− = ArbitraryValue { _unArbitraryValue :: Value }
31− deriving (Eq, Show)
32−
33−instance Arbitrary ArbitraryValue where
34− arbitrary = ArbitraryValue <$> sized f
35− where
36− f :: Int -> Gen Value
37− f n | n <= 1 = oneof nonRecursive
38− | otherwise = oneof $
39− fmap (Array . V.fromList) (traverse (const (f (n `div` 10)))
40− =<< (arbitrary :: Gen [()]))
41− : fmap (Object . HM.fromList) (traverse (const (g (n `div` 10)))
42− =<< (arbitrary :: Gen [()]))
43− : nonRecursive
44−
45− g :: Int -> Gen (Text, Value)
46− g n = (,) <$> arbitraryText <*> f n
47−
48− nonRecursive :: [Gen Value]
49− nonRecursive =
50− [ pure Null
51− , Bool <$> arbitrary
52− , String <$> arbitraryText
53− , Number <$> arbitraryScientific
54− ]
55−
56−arbitraryHashMap :: Arbitrary a => Gen (HashMap Text a)
57−arbitraryHashMap = HM.fromList . fmap (first T.pack) <$> arbitrary
58−
59−arbitrarySetOfText :: Gen (Set Text)
60−arbitrarySetOfText = S.fromList . fmap T.pack <$> arbitrary
61−
62−newtype NonEmpty' a = NonEmpty' { _unNonEmpty' :: NonEmpty a }
63−
64−instance FromJSON a => FromJSON (NonEmpty' a) where
65− parseJSON v = do
66− xs <- parseJSON v
67− case NE.nonEmpty xs of
68− Nothing -> fail "Must have at least one item."
69− Just ne -> pure (NonEmpty' ne)
70−
71−instance ToJSON a => ToJSON (NonEmpty' a) where
72− toJSON = toJSON . NE.toList . _unNonEmpty'
73−
74−instance Arbitrary a => Arbitrary (NonEmpty' a) where
75− arbitrary = do
76− xs <- arbitrary
77− case NE.nonEmpty xs of
78− Nothing -> NonEmpty' . pure <$> arbitrary
79− Just ne -> pure (NonEmpty' ne)
80−
81−--------------------------------------------------
82−-- * allUniqueValues
83−--------------------------------------------------
84−
85−allUniqueValues :: (Foldable f, Functor f) => f Value -> Bool
86−allUniqueValues = allUnique . fmap OrdValue
87−
88−allUnique :: (Foldable f, Ord a) => f a -> Bool
89−allUnique xs = S.size (S.fromList (toList xs)) == length xs
90−
91−-- | OrdValue's Ord instance needs benchmarking, but it allows us to
92−-- use our 'allUnique' function instead of O(n^2) nub, so it's probably
93−-- worth it.
94−newtype OrdValue = OrdValue { _unOrdValue :: Value } deriving Eq
95−
96−instance Ord OrdValue where
97− (OrdValue Null) `compare` (OrdValue Null) = EQ
98− (OrdValue Null) `compare` _ = LT
99− _ `compare` (OrdValue Null) = GT
100−
101− (OrdValue (Bool x)) `compare` (OrdValue (Bool y)) = x `compare` y
102− (OrdValue (Bool _)) `compare` _ = LT
103− _ `compare` (OrdValue (Bool _)) = GT
104−
105− (OrdValue (Number x)) `compare` (OrdValue (Number y)) = x `compare` y
106− (OrdValue (Number _)) `compare` _ = LT
107− _ `compare` (OrdValue (Number _)) = GT
108−
109− (OrdValue (String x)) `compare` (OrdValue (String y)) = x `compare` y
110− (OrdValue (String _)) `compare` _ = LT
111− _ `compare` (OrdValue (String _)) = GT
112−
113− (OrdValue (Array xs)) `compare` (OrdValue (Array ys)) =
114− (OrdValue <$> xs) `compare` (OrdValue <$> ys)
115− (OrdValue (Array _)) `compare` _ = LT
116− _ `compare` (OrdValue (Array _)) = GT
117−
118− (OrdValue (Object x)) `compare` (OrdValue (Object y)) =
119− HM.toList (OrdValue <$> x) `compare` HM.toList (OrdValue <$> y)
stack.yamldeleted−2
@@ -1,2 +0,0 @@
1−resolver: lts-10.8
2−pvp-bounds: upper-revision
test/Local.hsdeleted−98
@@ -1,98 +0,0 @@
1−module Main where
2−
3−import Protolude
4−
5−import Data.Aeson
6−import qualified Data.List.NonEmpty as NE
7−import qualified System.Timeout as TO
8−import Test.Hspec
9−import Test.QuickCheck (property)
10−
11−import qualified JSONSchema.Draft4 as D4
12−import qualified JSONSchema.Types as JT
13−import qualified Local.Failure
14−import qualified Local.Reference
15−import qualified Local.Validation
16−import Shared
17−
18−-- Examples
19−import qualified AlternateSchema
20−import qualified Simple
21−import qualified TwoStep
22−
23−dir :: FilePath
24−dir = "JSON-Schema-Test-Suite/tests/draft4"
25−
26−supplementDir :: FilePath
27−supplementDir = "test/supplement"
28−
29−main :: IO ()
30−main = do
31−
32− -- Language agnostic tests
33− ts <- readSchemaTests
34− dir
35− (\a -> not (isHTTPTest a || skipTest a))
36−
37− -- Custom supplements to the language agnostic tests
38− supplementTs <- readSchemaTests supplementDir (not . isHTTPTest)
39−
40− hspec $ do
41− describe "Examples" exampleTests
42− describe "QuickCheck" quickCheckTests
43− describe "Failure" Local.Failure.spec
44− describe "JSONSchema.Validator.Reference" Local.Reference.spec
45− describe "Supplementary validation tests written in Haskell"
46− Local.Validation.spec
47−
48− describe "Supplementary tests written in JSON (using the record based schema)"
49− (traverse_ (toTest (fmap timeout . validate)) supplementTs)
50− describe "Supplementary tests written in JSON (using the 'Value' based schema)"
51− (traverse_ (toTest (fmap timeout . validateExample)) supplementTs)
52−
53− describe "Language agnostic tests (using the record based schema)"
54− (traverse_ (toTest validate) ts)
55− describe "Language agnostic tests (using the 'Value' based schema)"
56− (traverse_ (toTest validateExample) ts)
57− where
58− timeout :: Expectation -> Expectation
59− timeout f = do
60− res <- TO.timeout 3000000 f
61− case res of
62− Nothing -> expectationFailure "timeout expired"
63− Just a -> pure a
64−
65− validate :: D4.Schema -> SchemaTestCase -> Expectation
66− validate s sc = do
67− res <- D4.fetchHTTPAndValidate (D4.SchemaWithURI s Nothing) (_scData sc)
68− let failures = case res of
69− Right () -> mempty
70− Left (D4.HVData a) -> NE.toList (D4._invalidFailures a)
71− other -> panic ("Local.validate error: "
72− <> show other)
73− assertResult sc failures
74−
75− validateExample :: JT.Schema -> SchemaTestCase -> Expectation
76− validateExample s sc = do
77− res <- AlternateSchema.referencesViaHTTP (D4.SchemaWithURI s Nothing)
78− case res of
79− Left e -> panic ("Local.validateExample error: " <> show e)
80− Right schemaMap -> do
81− let failures = AlternateSchema.validate
82− schemaMap
83− (D4.SchemaWithURI s Nothing)
84− (_scData sc)
85− assertResult sc failures
86−
87−quickCheckTests :: Spec
88−quickCheckTests =
89− it "schemas invert through JSON without change" $ do
90− property invertSchema
91− where
92− invertSchema :: D4.Schema -> Bool
93− invertSchema a = Just a == decode (encode a)
94−
95−exampleTests :: Spec
96−exampleTests = do
97− it "Simple.example compiles successfully" Simple.example
98− it "TwoStep.example compiles successfully" TwoStep.example
test/Local/Failure.hsdeleted−105
@@ -1,105 +0,0 @@
1−module Local.Failure where
2−
3−import Protolude
4−
5−import Data.Aeson
6−import qualified Data.Vector as V
7−import qualified JSONPointer as JP
8−import Test.Hspec
9−
10−import JSONSchema.Draft4
11−import qualified JSONSchema.Draft4.Spec as Spec
12−import qualified JSONSchema.Validator.Draft4 as VAL
13−
14−spec :: Spec
15−spec = do
16− it "items array failures are constructed correctly" itemsArray
17− it "items object failures are constructed correctly" itemsObject
18− it "reports infinitely looping references correctly" loopRef
19−
20−itemsArray :: Expectation
21−itemsArray =
22− failures `shouldBe`
23− [ FailureItems (VAL.ItemsArrayInvalid (
24− pure ( JP.Index 0
25− , pure (FailureUniqueItems (VAL.UniqueItemsInvalid
26− (V.fromList [Null, Null])
27− ))
28− )
29− ))
30− ]
31− where
32− failures :: [ValidatorFailure]
33− failures = Spec.specValidate mempty sw badData
34−
35− schema :: Schema
36− schema = emptySchema
37− { _schemaItems = Just $ VAL.ItemsArray
38− [emptySchema { _schemaUniqueItems = Just True }]
39− }
40−
41− sw :: SchemaWithURI Schema
42− sw = SchemaWithURI
43− { _swSchema = schema
44− , _swURI = Nothing
45− }
46−
47− badData :: Value
48− badData = toJSON [[Null, Null]]
49−
50−itemsObject :: Expectation
51−itemsObject =
52− failures `shouldBe`
53− [ FailureItems (VAL.ItemsObjectInvalid (
54− pure ( JP.Index 1
55− , pure (FailureUniqueItems (VAL.UniqueItemsInvalid
56− (V.fromList [Null, Null])
57− ))
58− )
59− ))
60− ]
61− where
62− failures :: [ValidatorFailure]
63− failures = Spec.specValidate mempty sw badData
64−
65− schema :: Schema
66− schema = emptySchema
67− { _schemaItems = Just $ VAL.ItemsObject
68− (emptySchema { _schemaUniqueItems = Just True })
69− }
70−
71− sw :: SchemaWithURI Schema
72− sw = SchemaWithURI
73− { _swSchema = schema
74− , _swURI = Nothing
75− }
76−
77− badData :: Value
78− badData = toJSON [Null, toJSON [Null, Null]]
79−
80−loopRef :: Expectation
81−loopRef =
82− failures `shouldBe`
83− [ FailureRef (VAL.RefLoop
84− "#"
85− (VAL.VisitedSchemas [(Nothing, Nothing)])
86− (Nothing, Nothing)
87− )
88− ]
89− where
90− failures :: [ValidatorFailure]
91− failures = Spec.specValidate mempty sw badData
92−
93− schema :: Schema
94− schema = emptySchema
95− { _schemaRef = Just "#"
96− }
97−
98− sw :: SchemaWithURI Schema
99− sw = SchemaWithURI
100− { _swSchema = schema
101− , _swURI = Nothing
102− }
103−
104− badData :: Value
105− badData = toJSON [[Null, Null]]
test/Local/Reference.hsdeleted−36
@@ -1,36 +0,0 @@
1−module Local.Reference where
2−
3−import Protolude
4−
5−import Test.Hspec
6−
7−import JSONSchema.Validator.Reference
8−
9−spec :: Spec
10−spec = do
11− it "updateResolutionScope gives correct results" $ do
12− updateResolutionScope (BaseURI Nothing) Nothing
13− `shouldBe` BaseURI Nothing
14−
15− updateResolutionScope (BaseURI Nothing) (Just "#")
16− `shouldBe` BaseURI Nothing
17−
18− updateResolutionScope (BaseURI Nothing) (Just "foo")
19− `shouldBe` BaseURI (Just "foo")
20−
21− -- TODO: Normalize after updateResolutionScope:
22− updateResolutionScope (BaseURI (Just "/foo")) (Just "./bar")
23− `shouldBe` BaseURI (Just "/./bar")
24−
25− it "resolveReference gives correct results" $ do
26− resolveReference (BaseURI (Just "/foo")) "bar"
27− `shouldBe` (Just "/bar", Nothing)
28−
29− resolveReference (BaseURI (Just "/foo/bar")) "/baz"
30− `shouldBe` (Just "/baz", Nothing)
31−
32− resolveReference (BaseURI Nothing) "#/bar"
33− `shouldBe` (Nothing, Just "/bar")
34−
35− resolveReference (BaseURI (Just "/foo")) "#/bar"
36− `shouldBe` (Just "/foo", Just "/bar")
test/Local/Validation.hsdeleted−70
@@ -1,70 +0,0 @@
1−module Local.Validation where
2−
3−import Protolude
4−
5−import Data.Aeson
6−import qualified Data.Aeson as AE
7−import qualified Data.HashMap.Strict as HM
8−import Data.String (String)
9−import Test.Hspec
10−
11−import qualified AlternateSchema as AS
12−import JSONSchema.Draft4
13−import qualified JSONSchema.Types as JT
14−
15−spec :: Spec
16−spec = do
17− -- Fetching from filesystem.
18−
19− it "a readFile exception during validation is turned into a left"
20− readFileException
21− it "Relative reference to local file"
22− (resolutionInvalid "test/Local/schema.json")
23− it "Chained relative references to local files"
24− (resolutionInvalid "./test/Local/schema-with-ref.json")
25−
26− -- Validation tests that were hard to write in JSON for whatever reason.
27−
28− it "Don't parse schemas that have Null in a forbidden location"
29− forbidNull
30− it "The 'Value' based Schema's checkSchema should catch Nulls"
31− exampleForbidNull
32−
33−readFileException :: Expectation
34−readFileException = do
35− let schema = emptySchema { _schemaRef = Just "does-not-exist.json" }
36− res <- referencesViaFilesystem (SchemaWithURI schema Nothing)
37− case res of
38− Left (FSReadFailure _) -> pure ()
39− a -> expectationFailure (msg <> show a)
40− where
41− msg :: String
42− msg = "expected referencesViaFilesystem to return ReadFailure,"
43− <> " instead got: "
44−
45−resolutionInvalid :: Text -> Expectation
46−resolutionInvalid ref = do
47− let schema = emptySchema { _schemaRef = Just ref }
48− res <- fetchFilesystemAndValidate (SchemaWithURI schema Nothing) badData
49− case res of
50− Left (FVData _) -> pure ()
51− a -> expectationFailure (msg <> show a)
52− where
53− badData :: Value
54− badData = toJSON [True, True]
55−
56− msg :: String
57− msg = "expected fetchFilesystemAndValidate to return"
58− <> " Left (FVData [_]), instead got: "
59−
60−forbidNull :: Expectation
61−forbidNull =
62− case fromJSON (Object (HM.singleton "type" Null)) of
63− AE.Error _ -> pure ()
64− AE.Success a -> expectationFailure ("parsed to: " <> show (a :: Schema))
65−
66−exampleForbidNull :: Expectation
67−exampleForbidNull =
68− case AS.checkSchema (JT.Schema (HM.singleton "type" Null)) of
69− [] -> expectationFailure "No checkSchema failures"
70− _ -> pure ()
test/Remote.hsdeleted−57
@@ -1,57 +0,0 @@
1−module Main where
2−
3−import Protolude
4−
5−import Control.Concurrent.Async (withAsync)
6−import qualified Data.List.NonEmpty as NE
7−import Network.Wai.Application.Static (defaultFileServerSettings,
8− staticApp)
9−import qualified Network.Wai.Handler.Warp as Warp
10−import Test.Hspec
11−
12−import qualified JSONSchema.Draft4 as D4
13−import qualified JSONSchema.Types as JT
14−import Shared
15−
16−-- Examples
17−import qualified AlternateSchema
18−
19−dir :: FilePath
20−dir = "JSON-Schema-Test-Suite/tests/draft4"
21−
22−main :: IO ()
23−main = withAsync serve $ \_ -> do
24− ts <- readSchemaTests dir isHTTPTest
25− hspec $ do
26− describe "Language agnostic tests (using the record based schema)"
27− (traverse_ (toTest validate) ts)
28− describe "Language agnostic tests (using the 'Value' based schema)"
29− (traverse_ (toTest validateExample) ts)
30− where
31− validate :: D4.Schema -> SchemaTestCase -> Expectation
32− validate s sc = do
33− res <- D4.fetchHTTPAndValidate (D4.SchemaWithURI s Nothing) (_scData sc)
34− let failures = case res of
35− Right () -> mempty
36− Left (D4.HVData a) -> NE.toList (D4._invalidFailures a)
37− other -> panic ("Local.validate error: "
38− <> show other)
39− assertResult sc failures
40−
41− validateExample :: JT.Schema -> SchemaTestCase -> Expectation
42− validateExample s sc = do
43− res <- AlternateSchema.referencesViaHTTP (D4.SchemaWithURI s Nothing)
44− case res of
45− Left e -> panic ("Remote.validateExample error: " <> show e)
46− Right schemaMap -> do
47− let failures = AlternateSchema.validate
48− schemaMap
49− (D4.SchemaWithURI s Nothing)
50− (_scData sc)
51− assertResult sc failures
52−
53−serve :: IO ()
54−serve = Warp.run 1234
55− . staticApp
56− . defaultFileServerSettings
57− $ "JSON-Schema-Test-Suite/remotes"
test/Shared.hsdeleted−134
@@ -1,134 +0,0 @@
1−module Shared where
2−
3−import Protolude
4−
5−import Control.Monad (fail)
6−import Data.Aeson
7−import Data.Aeson.TH (fieldLabelModifier)
8−import qualified Data.ByteString as BS
9−import Data.Char (toLower)
10−import Data.List (stripPrefix, unlines)
11−import qualified Data.Text as T
12−import qualified System.Directory as SD
13−import System.FilePath ((</>))
14−import Test.Hspec
15−
16−skipTest :: FilePath -> Bool
17−skipTest file = (file == "optional/format.json") -- Optional
18− || (file == "optional/zeroTerminatedFloats.json")
19− || (file == "optional/ecmascript-regex.json")
20−
21−
22−isHTTPTest :: FilePath -> Bool
23−isHTTPTest file = (file == "definitions.json")
24− || (file == "ref.json")
25− || (file == "refRemote.json")
26−
27−-- Recursively return the contents of a directory
28−-- (or return itself if given a file as an argument).
29−--
30−-- Return paths are relative to that directory.
31−listFiles :: FilePath -> IO [FilePath]
32−listFiles path = fmap ( fromMaybe "stripPrefix failed"
33− . stripPrefix (path <> "/")
34− ) <$> listFilesFullPath path
35−
36−-- Recursively return the contents of a directory
37−-- (or return itself if given a file as an argument).
38−--
39−-- All return paths start with the 'FilePath' argument.
40−listFilesFullPath :: FilePath -> IO [FilePath]
41−listFilesFullPath path = do
42− -- Check if it's a file or directory:
43− res <- SD.doesFileExist path
44− if res
45− then pure [path]
46− else do
47− fs <- fmap (path </>) <$> SD.listDirectory path
48− concat <$> traverse listFilesFullPath fs
49−
50−data SchemaTest = SchemaTest
51− { _stDescription :: Text
52− , _stSchema :: Value
53− , _stCases :: [SchemaTestCase]
54− }
55−
56−data SchemaTestCase = SchemaTestCase
57− { _scDescription :: Text
58− , _scData :: Value
59− , _scValid :: Bool
60− } deriving Generic
61−
62−instance FromJSON SchemaTest where
63− parseJSON = withObject "SchemaTest" $ \o -> SchemaTest
64− <$> o .: "description"
65− <*> o .: "schema"
66− <*> o .: "tests" -- Perhaps "cases" would have been
67− -- a more descriptive key.
68−
69−instance FromJSON SchemaTestCase where
70− parseJSON = genericParseJSON
71− defaultOptions
72− { fieldLabelModifier = fmap toLower . drop 3 }
73−
74−readSchemaTests
75− :: FilePath
76− -- ^ The path to a directory.
77− -> (FilePath -> Bool)
78− -- ^ A function to decide what we're interested in within that directory.
79− -> IO [SchemaTest]
80−readSchemaTests dir filterFunc = do
81− files <- filter filterFunc <$> listFiles dir
82− concat <$> traverse fileToCases files
83− where
84− -- Each file contains an array of SchemaTests, not just one.
85− fileToCases :: FilePath -> IO [SchemaTest]
86− fileToCases name = do
87− let fullPath = dir </> name
88− jsonBS <- BS.readFile fullPath
89− case eitherDecodeStrict jsonBS of
90− Left e -> fail $ "couldn't parse file '" <> fullPath <> "': " <> e
91− Right schemaTests -> pure $ prependFileName name <$> schemaTests
92−
93− prependFileName :: FilePath -> SchemaTest -> SchemaTest
94− prependFileName fileName s = s
95− { _stDescription = T.pack fileName <> ": " <> _stDescription s
96− }
97−
98−toTest
99− :: forall schema. FromJSON schema
100− => (schema -> SchemaTestCase -> Expectation)
101− -> SchemaTest
102− -> Spec
103−toTest validate st =
104− it (T.unpack (_stDescription st)) $
105− forM_ (_stCases st) (validate schema)
106− where
107− schema :: schema
108− schema = case fromJSON (_stSchema st) of
109− Error e -> panic ("Couldn't parse schema: " <> show e)
110− Success a -> a
111−
112−assertResult :: Show err => SchemaTestCase -> [err] -> Expectation
113−assertResult sc failures
114− | _scValid sc = assertValid sc failures
115− | otherwise = assertInvalid sc failures
116−
117−assertValid :: Show err => SchemaTestCase -> [err] -> Expectation
118−assertValid _ [] = pure ()
119−assertValid sc failures =
120− expectationFailure $ unlines
121− [ " Failed to validate data"
122− , " Description: " <> T.unpack (_scDescription sc)
123− , " Data: " <> show (_scData sc)
124− , " Validation failures: " <> show failures
125− ]
126−
127−assertInvalid :: SchemaTestCase -> [err] -> Expectation
128−assertInvalid sc [] =
129− expectationFailure $ unlines
130− [ " Validated invalid data"
131− , " Description: " <> T.unpack (_scDescription sc)
132− , " Data: " <> show (_scData sc)
133− ]
134−assertInvalid _ _ = pure ()
test/supplement/recurse.jsondeleted−17
@@ -1,17 +0,0 @@
1−[
2− {
3− "description": "recursive ref",
4− "schema": {
5− "allOf": [
6− {"$ref": "#"}
7− ]
8− },
9− "tests": [
10− {
11− "description": "arbitrary data",
12− "data": {},
13− "valid": false
14− }
15− ]
16− }
17−]
tests/Local.hsnew file+34
@@ -0,0 +1,34 @@
1+
2+module Main where
3+
4+import Control.Applicative
5+import Control.Monad (unless)
6+import Data.Aeson
7+import Data.List (isSuffixOf)
8+import Data.Monoid
9+import System.Directory (getDirectoryContents)
10+import Test.Tasty (defaultMain, testGroup)
11+import Test.Tasty.QuickCheck (testProperty)
12+
13+import Data.JsonSchema.Draft4
14+import Local.Failure (correctPaths)
15+import Local.Filesystem (fetchFromFilesystem)
16+import Local.Reference (referenceTests)
17+import Shared (isLocal, readSchemaTests, toTest)
18+
19+dir :: String
20+dir = "JSON-Schema-Test-Suite/tests/draft4"
21+
22+main :: IO ()
23+main = do
24+ filenames <- filter isLocal . filter (".json" `isSuffixOf`) <$> getDirectoryContents dir
25+ ts <- readSchemaTests dir filenames
26+ defaultMain . testGroup "Tests not requiring an HTTP server" $
27+ testProperty "Invert schemas through JSON without change" invertSchema
28+ : testGroup "Report the path to invalid data correctly" correctPaths
29+ : testGroup "Test the referencesViaFilesystem function" fetchFromFilesystem
30+ : testGroup "Test the Reference module" referenceTests
31+ : fmap toTest ts
32+
33+invertSchema :: Schema -> Bool
34+invertSchema a = Just a == decode (encode a)
tests/Local/Failure.hsnew file+55
@@ -0,0 +1,55 @@
1+
2+module Local.Failure where
3+
4+import Data.Aeson
5+import qualified Data.Aeson.Pointer as P
6+import Data.Monoid
7+import Test.Tasty (TestTree)
8+import qualified Test.Tasty.HUnit as HU
9+
10+import Data.JsonSchema.Draft4
11+import qualified Data.Validator.Draft4 as VA
12+
13+correctPaths :: [TestTree]
14+correctPaths =
15+ [ HU.testCase "Items object" itemsObject
16+ , HU.testCase "Items array" itemsArray
17+ ]
18+
19+itemsObject :: IO ()
20+itemsObject = HU.assertEqual "Path to invalid data"
21+ (P.Pointer [P.Token "0"])
22+ (_failureOffendingData failure)
23+ where
24+ [failure] = runValidate (ReferencedSchemas schema mempty)
25+ sw (toJSON [[True, True]])
26+
27+ schema :: Schema
28+ schema = emptySchema
29+ { _schemaItems = Just (VA.ItemsObject (emptySchema { _schemaUniqueItems = Just True }))
30+ }
31+
32+ sw :: SchemaWithURI Schema
33+ sw = SchemaWithURI
34+ { _swSchema = schema
35+ , _swURI = Nothing
36+ }
37+
38+itemsArray :: IO ()
39+itemsArray = HU.assertEqual "Path to invalid data"
40+ (P.Pointer [P.Token "0"])
41+ (_failureOffendingData failure)
42+ where
43+ [failure] = runValidate (ReferencedSchemas schema mempty)
44+ sw (toJSON [[True, True]])
45+
46+ schema :: Schema
47+ schema = emptySchema
48+ { _schemaItems = Just (VA.ItemsArray [emptySchema { _schemaUniqueItems = Just True }])
49+ }
50+
51+ sw :: SchemaWithURI Schema
52+ sw = SchemaWithURI
53+ { _swSchema = schema
54+ , _swURI = Nothing
55+ }
tests/Local/Filesystem.hsnew file+55
@@ -0,0 +1,55 @@
1+
2+module Local.Filesystem where
3+
4+import Data.Aeson
5+import Data.Monoid
6+import Test.Tasty (TestTree)
7+import qualified Test.Tasty.HUnit as HU
8+import Data.Text (Text)
9+
10+import Data.JsonSchema.Draft4
11+
12+fetchFromFilesystem :: [TestTree]
13+fetchFromFilesystem =
14+ [ HU.testCase
15+ "readFile exceptions are turned into Lefts"
16+ readFileExceptions
17+
18+ , HU.testCase
19+ "Relative reference to local file"
20+ (resolve "tests/Local/schema.json")
21+ , HU.testCase
22+ "Chained relative references to local files"
23+ (resolve "./tests/Local/schema-with-ref.json")
24+ ]
25+
26+readFileExceptions :: IO ()
27+readFileExceptions = do
28+ res <- referencesViaFilesystem (SchemaWithURI schema Nothing)
29+ case res of
30+ Left (ReadFailure _) -> pure ()
31+ a -> error (msg <> show a)
32+ where
33+ schema :: Schema
34+ schema = emptySchema { _schemaRef = Just "does-not-exist.json" }
35+
36+ msg :: String
37+ msg = "expected referencesViaFilesystem to return ReadFailure,"
38+ <> " instead got: "
39+
40+-- * Helpers
41+
42+resolve :: Text -> IO ()
43+resolve ref = do
44+ let schema = emptySchema { _schemaRef = Just ref }
45+ res <- fetchFilesystemAndValidate (SchemaWithURI schema Nothing) badData
46+ case res of
47+ Left (FVData _) -> pure ()
48+ a -> error (msg <> show a)
49+ where
50+ badData :: Value
51+ badData = toJSON [True, True]
52+
53+ msg :: String
54+ msg = "expected fetchFilesystemAndValidate to return"
55+ <> " Left (FVData [_]), instead got: "
tests/Local/Reference.hsnew file+51
@@ -0,0 +1,51 @@
1+
2+module Local.Reference where
3+
4+import Test.Tasty (TestTree)
5+import qualified Test.Tasty.HUnit as HU
6+
7+import Data.Validator.Reference
8+
9+referenceTests :: [TestTree]
10+referenceTests =
11+ [ HU.testCase "updateResolutionScope test cases" updateResolutionScopeTests
12+ , HU.testCase "resolveReference test cases" resolveReferenceTests
13+ ]
14+
15+updateResolutionScopeTests :: IO ()
16+updateResolutionScopeTests = do
17+ HU.assertEqual
18+ "case 1 result"
19+ Nothing
20+ (updateResolutionScope Nothing Nothing)
21+ HU.assertEqual
22+ "case 2 result"
23+ Nothing
24+ (updateResolutionScope Nothing (Just "#"))
25+ HU.assertEqual
26+ "case 3 result"
27+ (Just "foo")
28+ (updateResolutionScope Nothing (Just "foo"))
29+ HU.assertEqual
30+ "case 4 result"
31+ (Just "/./bar") -- TODO: Normalize after updateResolutionScope.
32+ (updateResolutionScope (Just "/foo") (Just "./bar"))
33+
34+resolveReferenceTests :: IO ()
35+resolveReferenceTests = do
36+ HU.assertEqual
37+ "case 1 result"
38+ (Just "/bar", Nothing)
39+ (resolveReference (Just "/foo") "bar")
40+ HU.assertEqual
41+ "case 2 result"
42+ (Just "/baz", Nothing)
43+ (resolveReference (Just "/foo/bar") "/baz")
44+ HU.assertEqual
45+ "case 3 result"
46+ (Nothing, Just "/bar")
47+ (resolveReference Nothing "#/bar")
48+ HU.assertEqual
49+ "case 4 result"
50+ (Just "/foo", Just "/bar")
51+ (resolveReference (Just "/foo") "#/bar")
test/Local/schema-with-ref.json → tests/Local/schema-with-ref.jsonrenamed

The content is the same.

test/Local/schema.json → tests/Local/schema.jsonrenamed

The content is the same.

tests/Remote.hsnew file+26
@@ -0,0 +1,26 @@
1+module Main where
2+
3+import Control.Applicative
4+import Control.Concurrent.Async (withAsync)
5+import Data.List (isSuffixOf)
6+import Network.Wai.Application.Static (defaultFileServerSettings,
7+ staticApp)
8+import Network.Wai.Handler.Warp (run)
9+import System.Directory (getDirectoryContents)
10+import Test.Tasty (defaultMain, testGroup)
11+
12+import Shared (isLocal, readSchemaTests,
13+ toTest)
14+
15+dir :: String
16+dir = "JSON-Schema-Test-Suite/tests/draft4"
17+
18+main :: IO ()
19+main = withAsync serve $ \_ -> do
20+ filenames <- filter (not . isLocal) . filter (".json" `isSuffixOf`)
21+ <$> getDirectoryContents dir
22+ ts <- readSchemaTests dir filenames
23+ defaultMain . testGroup "Tests that run an HTTP server" $ toTest <$> ts
24+
25+serve :: IO ()
26+serve = run 1234 . staticApp . defaultFileServerSettings $ "JSON-Schema-Test-Suite/remotes"
tests/Shared.hsnew file+99
@@ -0,0 +1,99 @@
1+{-# LANGUAGE DeriveGeneric #-}
2+
3+module Shared where
4+
5+import Control.Applicative
6+import Control.Monad
7+import Data.Aeson
8+import Data.Aeson.TH
9+import qualified Data.ByteString.Lazy as LBS
10+import Data.Char (toLower)
11+import Data.Monoid
12+import Data.Text (Text)
13+import qualified Data.Text as T
14+import GHC.Generics
15+import System.FilePath ((</>))
16+import Test.Tasty (TestTree)
17+import qualified Test.Tasty.HUnit as HU
18+
19+import qualified Data.JsonSchema.Draft4 as D4
20+
21+isLocal :: String -> Bool
22+isLocal file = (file /= "definitions.json")
23+ && (file /= "ref.json")
24+ && (file /= "refRemote.json")
25+
26+data SchemaTest = SchemaTest
27+ { _stDescription :: Text
28+ , _stSchema :: D4.Schema
29+ , _stCases :: [SchemaTestCase]
30+ }
31+
32+data SchemaTestCase = SchemaTestCase
33+ { _scDescription :: Text
34+ , _scData :: Value
35+ , _scValid :: Bool
36+ } deriving Generic
37+
38+instance FromJSON SchemaTest where
39+ parseJSON = withObject "SchemaTest" $ \o -> SchemaTest
40+ <$> o .: "description"
41+ <*> o .: "schema"
42+ <*> o .: "tests" -- Perhaps "cases" would have been a more descriptive key.
43+
44+instance FromJSON SchemaTestCase where
45+ parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = fmap toLower . drop 3 }
46+
47+readSchemaTests :: String -> [String] -> IO [SchemaTest]
48+readSchemaTests dir jsonFiles = concatMapM fileToCases jsonFiles
49+ where
50+ -- Each file contains an array of SchemaTests, not just one.
51+ fileToCases :: String -> IO [SchemaTest]
52+ fileToCases name = do
53+ let fullPath = dir </> name
54+ jsonBS <- LBS.readFile fullPath
55+ case eitherDecode jsonBS of
56+ Left e -> fail $ "couldn't parse file '" <> fullPath <> "': " <> e
57+ Right schemaTests -> pure $ prependFileName name <$> schemaTests
58+
59+ prependFileName :: String -> SchemaTest -> SchemaTest
60+ prependFileName fileName s = s
61+ { _stDescription = T.pack fileName <> ": " <> _stDescription s
62+ }
63+
64+ concatMapM :: (Monad m) => (a -> m [b]) -> [a] -> m [b]
65+ concatMapM f xs = liftM concat (mapM f xs)
66+
67+toTest :: SchemaTest -> TestTree
68+toTest st =
69+ HU.testCase (T.unpack (_stDescription st)) $ do
70+ forM_ (_stCases st) $ \sc -> do
71+ g <- assertRight =<< D4.referencesViaHTTP (D4.SchemaWithURI (_stSchema st) Nothing)
72+ validate <- assertRight . D4.checkSchema g $ D4.SchemaWithURI (_stSchema st) Nothing
73+ let res = validate (_scData sc)
74+ if _scValid sc
75+ then assertValid sc res
76+ else assertInvalid sc res
77+
78+assertValid :: SchemaTestCase -> [D4.Failure] -> HU.Assertion
79+assertValid _ [] = pure ()
80+assertValid sc errs =
81+ HU.assertFailure $ unlines
82+ [ " Failed to validate data"
83+ , " Description: " <> T.unpack (_scDescription sc)
84+ , " Data: " <> show (_scData sc)
85+ , " Validation failures: " <> show errs
86+ ]
87+
88+assertInvalid :: SchemaTestCase -> [D4.Failure] -> HU.Assertion
89+assertInvalid sc [] =
90+ HU.assertFailure $ unlines
91+ [ " Validated invalid data"
92+ , " Description: " <> T.unpack (_scDescription sc)
93+ , " Data: " <> show (_scData sc)
94+ ]
95+assertInvalid _ _ = pure ()
96+
97+assertRight :: (Show a) => Either a b -> IO b
98+assertRight (Left e) = HU.assertFailure (show e) >> fail "assertRight failed"
99+assertRight (Right b) = pure b