on master help sign in
Initial README
commita0b362eeedaeddf2f97a1649a6f694bdce5f4497 authorDenis Redozubov <denis.redozubov@gmail.com> dateSun 11 Jun 2017, 15:38 (9 years ago) parentce63ac6
1 file changed+110
README.md+110
README.md+110
@@ -1,3 +1,113 @@
11# schematic
22
33[![Build Status](https://travis-ci.org/dredozubov/schematic.svg?branch=master)](https://travis-ci.org/dredozubov/schematic)
4+
5+## Goal
6+
7+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](http://json-schema.org), 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:
8+
9+* All the instantiations of transport types are structurally follow the schema provided by user
10+* Serializers are generic, so they follow from the type-level schema and the're supposed to have roundtrip property by implementation.
11+* Runtime value validators are generated from the schema. Validation errors are reported as a pairs of a json-path to the element and an error message.
12+* There are migrations. It's possible to describe a series of migrations to the schema and have all the machinery deserialize a user specified version of the schema if there's a few versions.
13+
14+## TODO
15+
16+* Making a migration system more usable. It should allow it to be used as a json safecopy solution minus the boilerplate.
17+* Describing versioned http endpoints
18+* Schema pretty-printing
19+* More validators
20+* Overall user friendliness
21+
22+Be aware that library is experimental and subject to change a lot. The current state can be viewed as a prototype.
23+
24+## Installation
25+
26+* Install [Stack](https://github.com/commercialhaskell/stack)
27+
28+```
29+$ stack install schematic
30+```
31+
32+## Basic Examples
33+
34+```
35+type SchemaExample
36+ = SchemaObject
37+ '[ '("foo", SchemaArray '[AEq 1] (SchemaNumber '[NGt 10]))
38+ , '("bar", SchemaOptional (SchemaText '[TEnum '["foo", "bar"]]))]
39+```
40+
41+* This schema says that's structurally it's a JSON object which has two field:
42+ * field "foo" contains an of numeric values
43+ * field "bar" contains an optional textual value
44+* It also allows you to validate the JSON:
45+ * an array in "foo" must contain exactly one element
46+ * that element must be strictly greater than 10
47+ * value of bar must be either "foo" or "bar" if presented
48+
49+
50+This one is valid for example
51+
52+```
53+schemaJson :: ByteString
54+schemaJson = "{\"foo\": [13], \"bar\": null}"
55+```
56+
57+Also valid
58+
59+```
60+schemaJson :: ByteString
61+schemaJson = "{\"foo\": [13], \"bar\": \"bar\"}"
62+```
63+
64+it can be parsed and validated like this:
65+
66+```
67+decodeAndValidateJson schemaJson :: ParseResult (JsonRepr SchemaExample)
68+```
69+
70+`ParseResult` type encodes three possible situations:
71+* json is structurally consistent with schema and runtime validations passed
72+* json source is malformed or doesn't correspond to schema structurally
73+* some of the runtime validations failed, but it's structurally correct
74+
75+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.
76+
77+
78+```
79+jsonExample :: JsonRepr SchemaExample
80+jsonExample = ReprObject $
81+ FieldRepr (ReprArray [ReprNumber 12])
82+ :& FieldRepr (ReprOptional (Just (ReprText "bar")))
83+ :& RNil
84+```
85+
86+## Migrations
87+
88+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.
89+
90+This piece of code will apply a migration to the schema, then decodes and validates the latest version.
91+
92+```
93+type SchemaExample
94+ = SchemaObject
95+ '[ '("foo", SchemaArray '[AEq 1] (SchemaNumber '[NGt 10]))
96+ , '("bar", SchemaOptional (SchemaText '[TEnum '["foo", "bar"]]))]
97+
98+type TestMigration =
99+ 'Migration "test_revision"
100+ '[ 'Diff '[ 'PKey "bar" ] ('Update ('SchemaText '[]))
101+ , 'Diff '[ 'PKey "foo" ] ('Update ('SchemaNumber '[])) ]
102+
103+type VS = 'Versioned SchemaExample '[ TestMigration ]
104+
105+schemaJsonTopVersion :: ByteString
106+schemaJsonTopVersion = "{ \"foo\": 42, \"bar\": \"bar\" }"
107+```
108+
109+It's possible to decode the latest version like this:
110+
111+```
112+decodeAndValidateJson schemaJsonTopVersion :: ParseResult (JsonRepr (TopVersion (AllVersions VS)))
113+```