What is this?
Medea is a schema language for JSON document structure. It is similar to JSON Schema, but is designed to be simpler and more self-contained.
This repo contains both a specification (in
SPEC.md) and a reference
implementation (in Haskell). We also have a PureScript implementation available.
“I’m not sure if the name is because it loves JSON, or murdered all of JSON’s kids and flew away in a chariot pulled by dragons.”
Since JSON Schema exists, and has gone through a range of revisions, why does Medea exist? There are several reasons for this, which we summarize below.
The JSON Schema standard is complex
The current version of the JSON Schema standard (the 2019-09 draft at the time of writing) is highly complex. It, along with its adjacent standards, covers considerably more than simply validating JSON documents. It also includes:
- A MIME type for schema files
- Meta-schema information, including URI-based stuff
- Lexical and dynamic scope of keywords
- Sub-schemata and rules they follow
- Output formatting
- How to identify schemata via media type parameters
Note that this is before we get to anything to do with validating JSON! It is perhaps unsurprising that no Haskell package exists which complies with the current standard. Thus, we would have to develop something ‘from scratch’ in any case.
For our purposes, none of this was needed - we simply wanted to have a way to describe the valid structure of a JSON document in textual form, and have a way to use it as a cross-language tool for validating the structure of JSON. Medea focuses on this, and only this.
JSON Schema requires arbitrary URI resolution
Due to the design of JSON Schema, schemata themselves have (meta) schemata. These are indicated by use of URIs. Additionally, schemata can include other schemata, in several different ways, also indicating this by URIs. These URIs can aim at basically arbitrary locations; in fact, multiple examples in the standard(s) specify online locations where such information can be found.
This essentially means that a compliant validator must be able to follow arbitrary URIs, or give users the ability to direct the validator. This isn’t even needed for validation itself - we might need to do this just to know what the schema is! Furthermore, as canonical examples require us to fetch information from online (or have a means of users directing us there), any validator we create would need to support fetching data from the Internet.
While this can be useful, it puts considerable complexity on the part of both the validator and the user. The use case that prompted the creation of Medea didn’t (and still doesn’t) warrant this degree of complexity. This is not merely a question of implementation time or dependency weight - it is also an issue of correctness and usability. The design of Medea deliberately limits this - all schemata are single, self-contained files. How these files are obtained, and aimed at, is left to the user; if they need to fetch these from a remote location or not should not be Medea’s concern (and isn’t).
For an easy starting point, check out
TUTORIAL.md, which describes basic usage
of Medea, with examples. For a more detailed description of Medea’s capabilities
and schema language,
SPEC.md has you covered.
We also provide a collection of Medea schema files, designed for conformance
testing, in the
What does Medea work on?
We support every major GHC version from 8.6 onwards, for its most current minor version. At the moment, this means:
We support both Stack and Cabal (v2) builds. We aim to be cross-platform where possible - if the dependencies work on the platform, Medea should too.
Medea’s specification, as well as the Haskell (and PureScript) reference
implementations, are under the MIT license. Please see
LICENSE.md for more
- Widen QuickCheck bounds.
- Remove MonadError from the top-level API.
- Use strict, rather than lazy, bytestrings for parser input. This fixes issues with resource safety.
- Test with GHC 8.8.4.
stack.yamlto use LTS 15.15.
- Ship our .hspec file to ensure all tests pass from an sdist.
- Ship our conformance suite as part of the sdist.
- Widen bounds on
ParserError, and have the loader return it on parsing errors.
- Remove -O2 optimization flag for test-suite.
- Initial release