1-- | An implementation of JSON Schema Draft 4 based on 'HashMap Text Value'
2-- instead of a custom record type like 'JSONSchema.Draft4'.
4-- If you're writing code for a new schema specification you probably want
5-- to copy this module instead of the 'JSONSchema.Draft4'. While it's
6-- less convenient to write schemas in Haskell without a record type, you
7-- can get the implementation finished with far fewer lines of code.
8module AlternateSchema where
12import Data.Aeson (FromJSON(..), Value(..), decodeStrict)
13import qualified Data.Aeson as AE
14import qualified Data.HashMap.Strict as HM
15import Data.Maybe (fromMaybe)
16import Data.Profunctor (Profunctor(..))
18import JSONSchema.Draft4 (ValidatorFailure(..), metaSchemaBytes)
19import JSONSchema.Fetch (SchemaWithURI(..), URISchemaMap(..))
20import qualified JSONSchema.Fetch as FE
21import JSONSchema.Types (Schema(..), Spec(..))
22import qualified JSONSchema.Types as JT
23import qualified JSONSchema.Validator.Draft4 as D4
24import JSONSchema.Validator.Reference (BaseURI(..), Scope(..),
25 updateResolutionScope)
27--------------------------------------------------
28-- * Basic fetching tools
29--------------------------------------------------
32 :: SchemaWithURI Schema
33 -> IO (Either FE.HTTPFailure (FE.URISchemaMap Schema))
34referencesViaHTTP = FE.referencesViaHTTP' draft4FetchInfo
36draft4FetchInfo :: FE.FetchInfo Schema
37draft4FetchInfo = FE.FetchInfo embedded (lookup "id") (lookup "$ref")
39 lookup :: Text -> Schema -> Maybe Text
42 Just (String t) -> Just t
45-- | An implementation of 'JT.embedded'.
46embedded :: Schema -> ([Schema], [Schema])
48 JT.embedded (d4Spec mempty mempty (Scope s Nothing (BaseURI Nothing))) s
50--------------------------------------------------
52--------------------------------------------------
55 :: URISchemaMap Schema
56 -> SchemaWithURI Schema
59validate schemaMap sw =
60 JT.validate (d4Spec schemaMap visited scope) (_swSchema sw)
62 visited :: D4.VisitedSchemas
63 visited = D4.VisitedSchemas [(Nothing, Nothing)]
65 schemaId :: Maybe Text
66 schemaId = FE._fiId draft4FetchInfo (_swSchema sw)
70 { _topLevelDocument = _swSchema sw
71 , _documentURI = _swURI sw
72 , _currentBaseURI = updateResolutionScope (BaseURI (_swURI sw))
76-- | A schema for schemas themselves. Uses @src/draft4.json@ which is loaded
80 fromMaybe (panic "Schema decode failed (this should never happen)")
84checkSchema :: Schema -> [ValidatorFailure]
85checkSchema = validate schemaMap (SchemaWithURI metaSchema Nothing)
89 schemaMap :: URISchemaMap Schema
91 URISchemaMap (HM.singleton "http://json-schema.org/draft-04/schema"
94--------------------------------------------------
96--------------------------------------------------
99 :: URISchemaMap Schema
104 -> [ValidatorFailure]
105validateSubschema schemaMap visited scope schema =
106 JT.validate (d4Spec schemaMap visited newScope) schema
108 schemaId :: Maybe Text
109 schemaId = FE._fiId draft4FetchInfo schema
111 newScope :: Scope Schema
113 { _currentBaseURI = updateResolutionScope (_currentBaseURI scope)
118 :: URISchemaMap Schema
121 -> Spec Schema ValidatorFailure
122 -- ^ Here we reuses 'ValidatorFailure' from
123 -- 'JSONSchema.Draft4.Failure'. If your validators have different
124 -- failure possibilities you'll need to create your own validator
126d4Spec schemaMap visited scope =
131 (D4.refValidator (FE.getReference schemaMap) updateScope
132 valRef visited scope)
135 <> fmap (lmap disableIfRefPresent)
136 [ dimap f FailureMultipleOf D4.multipleOfValidator
137 , dimap f FailureMaximum D4.maximumValidator
138 , dimap f FailureMinimum D4.minimumValidator
140 , dimap f FailureMaxLength D4.maxLengthValidator
141 , dimap f FailureMinLength D4.minLengthValidator
142 , dimap f FailurePattern D4.patternValidator
144 , dimap f FailureMaxItems D4.maxItemsValidator
145 , dimap f FailureMinItems D4.minItemsValidator
146 , dimap f FailureUniqueItems D4.uniqueItemsValidator
148 (fromMaybe D4.emptyItems . f)
150 D4.IRInvalidItems e -> FailureItems e
151 D4.IRInvalidAdditional e -> FailureAdditionalItems e)
152 (D4.itemsRelatedValidator descend)
153 , lmap f D4.definitionsEmbedded
155 , dimap f FailureMaxProperties D4.maxPropertiesValidator
156 , dimap f FailureMinProperties D4.minPropertiesValidator
157 , dimap f FailureRequired D4.requiredValidator
158 , dimap f FailureDependencies (D4.dependenciesValidator descend)
160 (fromMaybe D4.emptyProperties . f)
161 FailurePropertiesRelated
162 (D4.propertiesRelatedValidator descend)
164 , dimap f FailureEnum D4.enumValidator
165 , dimap f FailureType D4.typeValidator
166 , dimap f FailureAllOf (D4.allOfValidator lateral)
167 , dimap f FailureAnyOf (D4.anyOfValidator lateral)
168 , dimap f FailureOneOf (D4.oneOfValidator lateral)
169 , dimap f FailureNot (D4.notValidator lateral)
172 f :: FromJSON a => Schema -> Maybe a
174 case AE.fromJSON (Object a) of
175 AE.Error _ -> Nothing
176 AE.Success b -> Just b
178 disableIfRefPresent :: Schema -> Schema
179 disableIfRefPresent schema =
180 case FE._fiRef draft4FetchInfo schema of
182 Just _ -> Schema mempty
184 updateScope :: BaseURI -> Schema -> BaseURI
185 updateScope uri schema =
186 updateResolutionScope uri (FE._fiId draft4FetchInfo schema)
193 -> [ValidatorFailure]
194 valRef vis sc = JT.validate (d4Spec schemaMap vis sc)
196 descend :: Schema -> Value -> [ValidatorFailure]
197 descend = validateSubschema schemaMap mempty scope
199 lateral :: Schema -> Value -> [ValidatorFailure]
200 lateral = validateSubschema schemaMap visited scope
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list