git.iko.soy/typeable/schematic
on 0.1.2.0 help sign in

type-safe JSON spec and validation tool

git clone https://git.iko.soy/typeable/schematic.git

schematic

Build Status

Goal

The goal of the library is to provide a type-safe transport layer for serializing and validating JSON. It can be thought of as a subset of json-schema, which is basically a specification of a JSON document. The other goal is getting as much as possible from this specification for free. Right now the following bits are prototyped:

TODO

Be aware that library is experimental and subject to change a lot. The current state can be viewed as a prototype.

Installation

$ stack install schematic

Basic Examples

type SchemaExample
  = SchemaObject
    '[ '("foo", SchemaArray '[AEq 1] (SchemaNumber '[NGt 10]))
     , '("bar", SchemaOptional (SchemaText '[TEnum '["foo", "bar"]]))]

This one is valid for example

schemaJson :: ByteString
schemaJson = "{\"foo\": [13], \"bar\": null}"

Also valid

schemaJson :: ByteString
schemaJson = "{\"foo\": [13], \"bar\": \"bar\"}"

it can be parsed and validated like this:

decodeAndValidateJson schemaJson :: ParseResult (JsonRepr SchemaExample)

ParseResult type encodes three possible situations:

I t's build a transport layer representation of that data that can be tranversed and transformed to whatever internal types user has. Transport layer represetation looks like this. Type parameter is the schema itself.

jsonExample :: JsonRepr SchemaExample
jsonExample = ReprObject $
  FieldRepr (ReprArray [ReprNumber 12])
    :& FieldRepr (ReprOptional (Just (ReprText "bar")))
    :& RNil

Migrations

It's possible to represent schema changes as a migration, which describes a series of json-path/change pairs. Migrations can be applied in succession.

This piece of code will apply a migration to the schema, then decodes and validates the latest version.

type SchemaExample
  = SchemaObject
    '[ '("foo", SchemaArray '[AEq 1] (SchemaNumber '[NGt 10]))
     , '("bar", SchemaOptional (SchemaText '[TEnum '["foo", "bar"]]))]

type TestMigration =
  'Migration "test_revision"
    '[ 'Diff '[ 'PKey "bar" ] ('Update ('SchemaText '[]))
     , 'Diff '[ 'PKey "foo" ] ('Update ('SchemaNumber '[])) ]

type VS = 'Versioned SchemaExample '[ TestMigration ]

schemaJsonTopVersion :: ByteString
schemaJsonTopVersion = "{ \"foo\": 42, \"bar\": \"bar\" }"

It's possible to decode the latest version like this:

decodeAndValidateJson schemaJsonTopVersion :: ParseResult (JsonRepr (TopVersion (AllVersions VS)))