git.iko.soy/typeable/schematic
on master help sign in
ChangeLog.md+11
since splitsnapshots
unifiedsplit
@@ -1,5 +1,16 @@
1# Revision history for schematic
1# Revision history for schematic
2
2
3+## 0.6.0.0 -- 2021-01-15
4+
5+Added compatability with aeson-1.4.3.0. Since version 1.4.3 the module `Data.Aeson` started exporting `JSONPath`, which was conflicting with our own `JSONPath`. Furthermore, started using `JSONPathElement` from `aeson` instead of `DemotedPathSegment`.
6+
7+## 0.5.1.0 -- 2021-01-15
8+
9+Fix the generation of json schema for numbers.
10+Add array constraints.
11+Fix the generation of text and number constraints.
12+Remove jsonpath from the error message.
13+
3## 0.5.0.0 -- 2019-02-20
14## 0.5.0.0 -- 2019-02-20
4
15
5GHC 8.6, json generation by schema definition, validation bug fixes, better
16GHC 8.6, json generation by schema definition, validation bug fixes, better
schematic.cabal+8−4
@@ -1,5 +1,5 @@
1name: schematic
1name: schematic
2−version: 0.5.0.0
2+version: 0.6.0.0
3synopsis: JSON-biased spec and validation tool
3synopsis: JSON-biased spec and validation tool
4description: JSON-biased spec and validation tool. Makes possible to have a schema as a haskell type and derive json instances, validation actions, JSON generation for property-test generically. Built-in lens support.
4description: JSON-biased spec and validation tool. Makes possible to have a schema as a haskell type and derive json instances, validation actions, JSON generation for property-test generically. Built-in lens support.
5license: BSD3
5license: BSD3
@@ -10,7 +10,7 @@ homepage: http://github.com/typeable/schematic
10Bug-reports: http://github.com/typeable/schematic/issues/
10Bug-reports: http://github.com/typeable/schematic/issues/
11category: Data
11category: Data
12build-type: Simple
12build-type: Simple
13−extra-source-files: ChangeLog.md
13+extra-source-files: ChangeLog.md, README.md
14cabal-version: >=1.10
14cabal-version: >=1.10
15
15
16library
16library
@@ -65,9 +65,9 @@ library
65 , TypeOperators
65 , TypeOperators
66 , TypeSynonymInstances
66 , TypeSynonymInstances
67 , UndecidableInstances
67 , UndecidableInstances
68− build-depends: base >=4.11 && <4.13
68+ build-depends: base >=4.11 && <5
69 , bytestring
69 , bytestring
70− , aeson >= 1
70+ , aeson >= 1.4.3.0 && < 1.6
71 , containers
71 , containers
72 , hjsonschema
72 , hjsonschema
73 , mtl
73 , mtl
@@ -118,3 +118,7 @@ test-suite spec
118 , HelpersSpec
118 , HelpersSpec
119 , LensSpec
119 , LensSpec
120 , JsonSchemaSpec
120 , JsonSchemaSpec
121+
122+source-repository head
123+ type: git
124+ location: https://github.com/typeable/schematic
src/Data/Schematic/JsonSchema.hs+5−4
@@ -47,11 +47,12 @@ textConstraint (DTEnum ss) =
47numberConstraint :: DemotedNumberConstraint -> State D4.Schema ()
47numberConstraint :: DemotedNumberConstraint -> State D4.Schema ()
48numberConstraint (DNLe n) = modify $ \s -> s
48numberConstraint (DNLe n) = modify $ \s -> s
49 { _schemaMaximum = pure . fromIntegral $ n }
49 { _schemaMaximum = pure . fromIntegral $ n }
50−numberConstraint (DNLt n) =
50+numberConstraint (DNLt n) = modify $ \s -> s
51− let n' = if n == 0 then 0 else n - 1
52− in modify $ \s -> s { _schemaMaximum = pure . fromIntegral $ n' }
51+ { _schemaMaximum = pure . fromIntegral $ n
52+ , _schemaExclusiveMaximum = pure True }
53numberConstraint (DNGt n) = modify $ \s -> s
53numberConstraint (DNGt n) = modify $ \s -> s
54− { _schemaMinimum = pure . fromIntegral $ n + 1 }
54+ { _schemaMinimum = pure . fromIntegral $ n
55+ , _schemaExclusiveMinimum = pure True }
55numberConstraint (DNGe n) = modify $ \s -> s
56numberConstraint (DNGe n) = modify $ \s -> s
56 { _schemaMinimum = pure . fromIntegral $ n }
57 { _schemaMinimum = pure . fromIntegral $ n }
57numberConstraint (DNEq n) = modify $ \s -> s
58numberConstraint (DNEq n) = modify $ \s -> s
src/Data/Schematic/Path.hs+17−20
@@ -4,36 +4,33 @@ import Data.Foldable as F
4import Data.Singletons.Prelude
4import Data.Singletons.Prelude
5import Data.Singletons.TypeLits
5import Data.Singletons.TypeLits
6import Data.Text as T
6import Data.Text as T
7+import Data.Aeson.Internal
7
8
8
9
9−data PathSegment = Key Symbol | Ix Nat
10+newtype JSONPathText = JSONPathText Text
10−
11−data instance Sing (jp :: PathSegment) where
12− SKey :: (SingI k) => Sing (k :: Symbol) -> Sing ('Key k)
13− SIx :: (SingI n) => Sing (n :: Nat) -> Sing ('Ix n)
14−
15−data DemotedPathSegment = DKey Text | DIx Integer
16 deriving (Show)
11 deriving (Show)
17
12
18−-- | Textual representation of json path.
13+data PathSegment = PathKey Symbol | PathIx Nat
19−newtype JSONPath = JSONPath Text
14+
20− deriving (Show)
15+data instance Sing (jp :: PathSegment) where
16+ SKey :: (SingI k) => Sing (k :: Symbol) -> Sing ('PathKey k)
17+ SIx :: (SingI n) => Sing (n :: Nat) -> Sing ('PathIx n)
21
18
22−demotePath :: Sing (ps :: [PathSegment]) -> [DemotedPathSegment]
19+demotePath :: Sing (ps :: [PathSegment]) -> JSONPath
23demotePath = go []
20demotePath = go []
24 where
21 where
25− go :: [DemotedPathSegment] -> Sing (ps :: [PathSegment]) -> [DemotedPathSegment]
22+ go :: JSONPath -> Sing (ps :: [PathSegment]) -> JSONPath
26 go acc SNil = acc
23 go acc SNil = acc
27 go acc (SCons p ps) = go (acc ++ [demotePathSeg p]) ps
24 go acc (SCons p ps) = go (acc ++ [demotePathSeg p]) ps
28− demotePathSeg :: Sing (ps :: PathSegment) -> DemotedPathSegment
25+ demotePathSeg :: Sing (ps :: PathSegment) -> JSONPathElement
29− demotePathSeg (SKey s) = DKey $ T.pack $ withKnownSymbol s $ symbolVal s
26+ demotePathSeg (SKey s) = Key $ T.pack $ withKnownSymbol s $ symbolVal s
30− demotePathSeg (SIx n) = DIx $ withKnownNat n $ fromIntegral $ natVal n
27+ demotePathSeg (SIx n) = Index $ withKnownNat n $ fromIntegral $ natVal n
31
28
32−demotedPathToText :: [DemotedPathSegment] -> JSONPath
29+demotedPathToText :: JSONPath -> JSONPathText
33−demotedPathToText = JSONPath . F.foldl' renderPathSegment ""
30+demotedPathToText = JSONPathText . F.foldl' renderPathSegment ""
34 where
31 where
35− renderPathSegment acc (DKey t) = acc <> "." <> t
32+ renderPathSegment acc (Key t) = acc <> "." <> t
36− renderPathSegment acc (DIx n) = acc <> "[" <> T.pack (show n) <> "]"
33+ renderPathSegment acc (Index n) = acc <> "[" <> T.pack (show n) <> "]"
37
34
38−pathToText :: Sing (ps :: [PathSegment]) -> JSONPath
35+pathToText :: Sing (ps :: [PathSegment]) -> JSONPathText
39pathToText = demotedPathToText . demotePath
36pathToText = demotedPathToText . demotePath
src/Data/Schematic/Validation.hs+11−10
@@ -3,6 +3,7 @@ module Data.Schematic.Validation where
3import Control.Monad
3import Control.Monad
4import Control.Monad.Validation
4import Control.Monad.Validation
5import Data.Aeson
5import Data.Aeson
6+import Data.Aeson.Internal
6import Data.Aeson.Types
7import Data.Aeson.Types
7import Data.Foldable
8import Data.Foldable
8import Data.Functor.Identity
9import Data.Functor.Identity
@@ -49,11 +50,11 @@ isValidationError (ValidationError _) = True
49isValidationError _ = False
50isValidationError _ = False
50
51
51validateTextConstraint
52validateTextConstraint
52− :: JSONPath
53+ :: JSONPathText
53 -> Text
54 -> Text
54 -> Sing (tcs :: TextConstraint)
55 -> Sing (tcs :: TextConstraint)
55 -> Validation ()
56 -> Validation ()
56−validateTextConstraint (JSONPath path) t = \case
57+validateTextConstraint (JSONPathText path) t = \case
57 STEq n -> do
58 STEq n -> do
58 let
59 let
59 nlen = withKnownNat n $ natVal n
60 nlen = withKnownNat n $ natVal n
@@ -106,11 +107,11 @@ validateTextConstraint (JSONPath path) t = \case
106 unless (matching ss) warn
107 unless (matching ss) warn
107
108
108validateNumberConstraint
109validateNumberConstraint
109− :: JSONPath
110+ :: JSONPathText
110 -> Scientific
111 -> Scientific
111 -> Sing (tcs :: NumberConstraint)
112 -> Sing (tcs :: NumberConstraint)
112 -> Validation ()
113 -> Validation ()
113−validateNumberConstraint (JSONPath path) num = \case
114+validateNumberConstraint (JSONPathText path) num = \case
114 SNEq n -> do
115 SNEq n -> do
115 let
116 let
116 nlen = withKnownNat n $ natVal n
117 nlen = withKnownNat n $ natVal n
@@ -148,11 +149,11 @@ validateNumberConstraint (JSONPath path) num = \case
148 unless predicate warn
149 unless predicate warn
149
150
150validateArrayConstraint
151validateArrayConstraint
151− :: JSONPath
152+ :: JSONPathText
152 -> V.Vector a
153 -> V.Vector a
153 -> Sing (tcs :: ArrayConstraint)
154 -> Sing (tcs :: ArrayConstraint)
154 -> Validation ()
155 -> Validation ()
155−validateArrayConstraint (JSONPath path) v = \case
156+validateArrayConstraint (JSONPathText path) v = \case
156 SAEq n -> do
157 SAEq n -> do
157 let
158 let
158 nlen = withKnownNat n $ natVal n
159 nlen = withKnownNat n $ natVal n
@@ -191,7 +192,7 @@ validateArrayConstraint (JSONPath path) v = \case
191
192
192validateJsonRepr
193validateJsonRepr
193 :: Sing schema
194 :: Sing schema
194− -> [DemotedPathSegment]
195+ -> JSONPath
195 -> JsonRepr schema
196 -> JsonRepr schema
196 -> Validation ()
197 -> Validation ()
197validateJsonRepr sschema dpath jr = case jr of
198validateJsonRepr sschema dpath jr = case jr of
@@ -225,7 +226,7 @@ validateJsonRepr sschema dpath jr = case jr of
225 process cs
226 process cs
226 process acs
227 process acs
227 for_ (V.indexed v) $ \(ix, jr') -> do
228 for_ (V.indexed v) $ \(ix, jr') -> do
228− let newPath = dpath <> pure (DIx $ fromIntegral ix)
229+ let newPath = dpath <> pure (Index $ fromIntegral ix)
229 validateJsonRepr s newPath jr'
230 validateJsonRepr s newPath jr'
230 ReprOptional d -> case sschema of
231 ReprOptional d -> case sschema of
231 SSchemaOptional ss -> case d of
232 SSchemaOptional ss -> case d of
@@ -237,7 +238,7 @@ validateJsonRepr sschema dpath jr = case jr of
237 go :: Rec FieldRepr (ts :: [(Symbol, Schema)] ) -> Validation ()
238 go :: Rec FieldRepr (ts :: [(Symbol, Schema)] ) -> Validation ()
238 go RNil = pure ()
239 go RNil = pure ()
239 go (f@(FieldRepr d) :& ftl) = do
240 go (f@(FieldRepr d) :& ftl) = do
240− let newPath = dpath <> [DKey (knownFieldName f)]
241+ let newPath = dpath <> [Key (knownFieldName f)]
241 validateJsonRepr (knownFieldSchema f) newPath d
242 validateJsonRepr (knownFieldSchema f) newPath d
242 go ftl
243 go ftl
243 ReprUnion _ -> pure () -- FIXME
244 ReprUnion _ -> pure () -- FIXME
@@ -249,7 +250,7 @@ validateJsonRepr sschema dpath jr = case jr of
249 -- fail "impossible to produce subUnion, please report this as a bug"
250 -- fail "impossible to produce subUnion, please report this as a bug"
250 -- Just x -> do
251 -- Just x -> do
251 -- let
252 -- let
252− -- JSONPath path = demotedPathToText dpath
253+ -- JSONPathText path = demotedPathToText dpath
253 -- case stl of
254 -- case stl of
254 -- SNil -> void $ vWarning $ mmSingleton path
255 -- SNil -> void $ vWarning $ mmSingleton path
255 -- $ pure "union handling error, please report this as bug"
256 -- $ pure "union handling error, please report this as bug"
stack-13.21.yamlnew file+7
@@ -0,0 +1,7 @@
1+resolver: lts-13.21
2+extra-deps:
3+ - hjsonpointer-1.4.0@rev:0
4+ - hjsonschema-1.9.0@rev:0
5+ - validationt-0.3.0
6+nix:
7+ packages: [pcre, pkg-config, zlib]
stack-13.7.yamldeleted−5
@@ -1,5 +0,0 @@
1−resolver: lts-13.7
2−extra-deps:
3− - hjsonpointer-1.4.0@rev:0
4− - hjsonschema-1.9.0@rev:0
5− - validationt-0.2.1.0
stack.yaml+5−4
@@ -1,5 +1,6 @@
1−resolver: lts-12.0
1+resolver: lts-14.22
2extra-deps:
2extra-deps:
3− - hjsonpointer-1.4.0@rev:0
3+- hjsonpointer-1.4.0@rev:0
4− - hjsonschema-1.9.0@rev:0
4+- hjsonschema-1.9.0@rev:0
5− - validationt-0.2.1.0
5+- git: https://github.com/typeable/validationt.git
6+ commit: 97fea97c4015ab5e99f3efb2c73e1fef4b8857d8
test/JsonSchemaSpec.hs+3−3
@@ -76,10 +76,10 @@ spec = do
76 let
76 let
77 schema = D4.SchemaWithURI (fromJust $ toJsonSchema (Proxy @SchemaNumberExample)) Nothing
77 schema = D4.SchemaWithURI (fromJust $ toJsonSchema (Proxy @SchemaNumberExample)) Nothing
78 obj = withRepr @SchemaNumberExample $
78 obj = withRepr @SchemaNumberExample $
79− field @"n1" 2
79+ field @"n1" 1.1
80 :& field @"n2" 1
80 :& field @"n2" 1
81− :& field @"n3" 0
81+ :& field @"n3" 0.9
82− :& field @"n4" 1
82+ :& field @"n4" 1.0
83 :& RNil
83 :& RNil
84 fetchHTTPAndValidate schema (toJSON obj) >>= \case
84 fetchHTTPAndValidate schema (toJSON obj) >>= \case
85 Left e -> fail "failed to validate test example"
85 Left e -> fail "failed to validate test example"