hjsonschema logo

A Haskell implementation of the current JSON Schema specification (Draft 4).

Hackage / GitHub / Travis CI

Requires pcre (pkgs.pcre in Nixpkgs).

NOTE: Schemas with circular references can cause infinite loops. hjsonschema does loop detection but it may not be solid yet – please open an issue if you find a situation where it fails.


See here.


Run all tests:

stack test

Run only local tests:

stack test hjsonschema:local

Run remote tests (makes GETs to json-schema.org, also temporarily starts an HTTP server on port 1234):

stack test hjsonschema:remote



  • Be a correct and fast implementation of the spec.

  • Be a useful reference for implementers in other languages. Haskell’s high level nature, expressive type system and referential transparency suit this purpose well.

Good Parts

  • Passes all the required tests in the language agnostic test suite.

  • Very modular, which should make it easy to support future versions of the specification.

Bad Parts

  • Uses the pcre-heavy regular expression library for the “pattern” validator. It should use a library based on the ECMA 262 regex dialect, which the spec requires.

  • Currently doesn’t support the optional "format" validators.


  • JSON-Schema-Test-Suite is vendored from commit # aabcb3427745ade7a0b4d49ff016ad7eda8b898b here.

  • src/draft4.json is from commit # f3d5aeb5ffbe9d9a5a0ceb761dc47c7c4c2efa68 here.


TJ Weigel created the logo.

Tim Baumann wrote aeson-schema, on which hjsonschema’s test code and its implementation of SchemaGraph were based.

Julian Berman maintains the fantastic language agnostic test suite.



+ Bump `aeson` and `hjsonpointer`.


+ Rename `schemaForSchemas` to `metaSchema` and `schemaForSchemasBytes` to


## Bug fixes:

+ Fix JSON Pointer bug. Pointers were being built in reverse order and so were
totally invalid.
+ 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.

## API Changes:

+ Add referenced schema loop detection.
+ Add a new `referencesValidity` function.
+ `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.
+ Switch most of the fetching code to use `URISchemaMap` instead of
`ReferencedSchemas`. It didn't need to know about the more complicated data
+ Rething failure related names. Change `Invalid` to `Failure`, add a new
`Invalid` type alias which is only used for final results.
+ 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.

## Fundamental Changes:

+ Make `Fail` (previously `Failure`) an instance of `Functor`.
+ Add a `Validator` data type which is an instance of `Profunctor`.
+ Add a `Spec` data type for collections of `Validators`.

## General:

+ Switch from 2 to 4 space indentation.
+ Update the vendored JSON Schema Test Suite.


+ Bump http-client.


+ Enable GHC 8.


+ Fix .cabal file.

# 0.10

+ Rewrite fetching internals.
+ Fix reference resolution defects, add more tests.
+ Switch to a Perl style regex library, which is closer to ECMAScript regexes
than the previous Posix style one.
+ Add one-step validation functions ('fetchFilesystemAndValidate' and 'fetchHTTPAndValidate').
+ Alias the validation failure type exported by 'Data.JsonSchema.Draft4' to
'Invalid', change its field names.

# 0.9

+ Partial rewrite. The API of the library has changed, see the examples
folder for how to use the new one.

+ Users of the library can now write schemas in Haskell as well as JSON.

# 0.8

+ Improve scope updating and resolving.
+ Rename RawSchema's _rsObject field to _rsData.
+ Make RawSchema's _rsURI field a Maybe. This way schemas without a starting
URI can say so explicitly with Nothing instead of with "".
+ 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. "#").
+ Change the order of the last two arguments to fetchReferencedSchemas.

# 0.7.1

+ Support GHC 7.8 again.

# 0.7

Change error type from Text to ValidationFailure.

Revert the 0.6 changes to validate. Also switch from Vector
to list. Validate is now:
Schema err -> Value -> [ValidationFailure err]

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.

# 0.6

Break the API so the library doesn't induce boolean blindness.

Change validate
was: Schema -> Value -> Vector ValErr
now: Schema -> Value -> Either (Vector ValErr) Value

Change Schema
was: type Schema = Vector Validator
now: newtype Schema = Schema { _unSchema :: [Validator] }

# 0.5.3

+ Switch from http-conduit to http-client.

# 0.5.2

+ Add convenience function for validating and compiling draft 4 schemas

# 0.5.1

+ Switch from wreq to http-conduit; drop lens dependency.

# 0.5

+ Start changelog.
+ Rename Utils.hs to Helpers.hs.
+ Move all non-ValidatorGen functions in Validators.hs to Helpers.hs.
+ Various touchups.