{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Applicative
import Data.Aeson
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as H
import Data.Monoid
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Vector as V
import qualified Data.JsonSchema as JS
-- Data.JsonSchema is designed to be imported unqualified.
-- We're just being explicit here for example purposes.
main :: IO ()
main = do
simpleExample
fullExample
--------------------------------------------------
-- * Example Schema and Data
--------------------------------------------------
schemaData :: JS.RawSchema
schemaData = JS.RawSchema
{ JS._rsURI = Nothing
-- ^ If your schema has relative references to other schemas
-- then you'll need to include this.
, JS._rsData = schemaJSON
}
where
schemaJSON :: HashMap Text Value
schemaJSON = H.singleton "uniqueItems" (Bool True)
badData :: Value
badData = Array $ V.fromList ["foo", "foo"]
--------------------------------------------------
-- * Simple Example
--------------------------------------------------
-- | Since our schema contains no references to other schemas,
-- we can skip the fetchGraph step.
simpleExample :: IO ()
simpleExample = do
schema <- compileSchema (JS.SchemaGraph schemaData H.empty) schemaData
checkResults (JS.validate schema badData)
--------------------------------------------------
-- * Full Example
--------------------------------------------------
-- | For a schema that might contain references to other schemas.
fullExample :: IO ()
fullExample = do
let currentSchemaCache = H.empty
schemaGraph <- fetchGraph currentSchemaCache schemaData
-- We aren't going to use it for anything this time, but if we were caching
-- remote schemas this would be our new cache.
--
-- let newSchemaCache = _cachedSchemas schemaData <> currentSchemaGraph
schema <- compileSchema schemaGraph schemaData
checkResults (JS.validate schema badData)
where
fetchGraph :: HashMap Text (HashMap Text Value) -> JS.RawSchema -> IO JS.SchemaGraph
fetchGraph graph rs = do
eitherGraph <- JS.fetchReferencedSchemas JS.draft4 graph rs
case eitherGraph of
Left e -> error $ "Failed to fetch graph with error: " <> T.unpack e
Right g -> return g
--------------------------------------------------
-- * Helper Functions
--------------------------------------------------
compileSchema :: JS.SchemaGraph -> JS.RawSchema -> IO (JS.Schema JS.Draft4Failure)
compileSchema graph rs =
case JS.compileDraft4 graph rs of
Left failure -> error $ "Not a valid schema: " <> show failure
Right schema -> return schema
checkResults :: [JS.ValidationFailure JS.Draft4Failure] -> IO ()
checkResults [] = error "OHNO we validated bad data!"
checkResults [JS.ValidationFailure JS.UniqueItems (JS.FailureInfo x y)] =
putStrLn . unlines $
[ ""
, "Success. We got a UniqueItems error as expected."
, "Here's the relevant part of the bad JSON document:"
, ""
, " " <> show y
, ""
, "And here's the content of the validator that caught it:"
, ""
, " " <> show x
]
checkResults x = error $ "OHNO we got a different failure than we expected: " <> show x