module Data.JSON.Schema.Types
( JSONSchema (..)
, Schema (..)
, Field (..)
, Bound (..)
, LengthBound (..)
, unbounded
, unboundedLength
) where
import Data.Fixed
import Data.Int
import Data.Maybe
import Data.Proxy
import Data.Scientific
import Data.String
import Data.Text (Text)
import Data.Time.Clock (UTCTime)
import Data.Vector (Vector)
import Data.Word
import qualified Data.Aeson.Types as Aeson
import qualified Data.HashMap.Strict as H
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Data.Text.Lazy as L
import qualified Data.Vector as V
data Schema =
Choice [Schema]
| Object [Field]
| Map Schema
| Array LengthBound Bool Schema
| Tuple [Schema]
| Value LengthBound
| Boolean
| Number Bound
| Constant Aeson.Value
| Any
deriving (Eq, Show)
data Bound = Bound
{ lower :: Maybe Int
, upper :: Maybe Int
} deriving (Eq, Show)
data LengthBound = LengthBound
{ lowerLength :: Maybe Int
, upperLength :: Maybe Int
} deriving (Eq, Show)
unbounded :: Bound
unbounded = Bound Nothing Nothing
integralSchema :: forall a. (Bounded a, Integral a) => Proxy a -> Schema
integralSchema _ =
Number $ Bound (Just $ fromIntegral (minBound::a))
(Just $ fromIntegral (maxBound::a))
unboundedLength :: LengthBound
unboundedLength = LengthBound Nothing Nothing
data Field = Field { key :: Text, required :: Bool, content :: Schema } deriving (Eq, Show)
class JSONSchema a where
schema :: Proxy a -> Schema
instance JSONSchema () where
schema _ = Constant Aeson.Null
instance JSONSchema Int where
schema _ = Number unbounded
instance JSONSchema Integer where
schema _ = Number unbounded
instance JSONSchema Int8 where
schema = integralSchema
instance JSONSchema Int16 where
schema = integralSchema
instance JSONSchema Int32 where
schema _ = Number unbounded
instance JSONSchema Int64 where
schema _ = Number unbounded
instance JSONSchema Word where
schema _ = Number (Bound (Just 0) Nothing)
instance JSONSchema Word8 where
schema = integralSchema
instance JSONSchema Word16 where
schema = integralSchema
instance JSONSchema Word32 where
schema _ = Number (Bound (Just 0) Nothing)
instance JSONSchema Word64 where
schema _ = Number (Bound (Just 0) Nothing)
instance JSONSchema Float where
schema _ = Number unbounded
instance JSONSchema Double where
schema _ = Number unbounded
instance HasResolution a => JSONSchema (Fixed a) where
schema _ = Number unbounded
instance JSONSchema Scientific where
schema _ = Number unbounded
instance JSONSchema Bool where
schema _ = Boolean
instance JSONSchema Text where
schema _ = Value unboundedLength
instance JSONSchema L.Text where
schema _ = Value unboundedLength
instance JSONSchema a => JSONSchema (Maybe a) where
schema p = Choice [Object [Field "Just" True $ schema $ fmap fromJust p], Object [Field "Nothing" True (Constant Aeson.Null)]]
instance JSONSchema a => JSONSchema [a] where
schema = Array unboundedLength False . schema . fmap head
instance JSONSchema a => JSONSchema (Vector a) where
schema = Array unboundedLength False . schema . fmap V.head
instance (IsString k, JSONSchema v) => JSONSchema (M.Map k v) where
schema = Map . schema . fmap (head . M.elems)
instance (IsString k, JSONSchema v) => JSONSchema (H.HashMap k v) where
schema = Map . schema . fmap (head . H.elems)
instance JSONSchema UTCTime where
schema _ = Value LengthBound { lowerLength = Just 20, upperLength = Just 33 }
instance JSONSchema a => JSONSchema (S.Set a) where
schema = Array unboundedLength True . schema . fmap S.findMin
instance JSONSchema Aeson.Value where
schema _ = Any
instance (JSONSchema a, JSONSchema b) => JSONSchema (a, b) where
schema s = Tuple
[ schema . fmap fst $ s
, schema . fmap snd $ s
]
instance (JSONSchema a, JSONSchema b, JSONSchema c) => JSONSchema (a, b, c) where
schema s = Tuple
[ schema . fmap (\(a,_,_) -> a) $ s
, schema . fmap (\(_,b,_) -> b) $ s
, schema . fmap (\(_,_,c) -> c) $ s
]
instance (JSONSchema a, JSONSchema b, JSONSchema c, JSONSchema d) => JSONSchema (a, b, c, d) where
schema s = Tuple
[ schema . fmap (\(a,_,_,_) -> a) $ s
, schema . fmap (\(_,b,_,_) -> b) $ s
, schema . fmap (\(_,_,c,_) -> c) $ s
, schema . fmap (\(_,_,_,d) -> d) $ s
]
instance (JSONSchema a, JSONSchema b, JSONSchema c, JSONSchema d, JSONSchema e) => JSONSchema (a, b, c, d, e) where
schema s = Tuple
[ schema . fmap (\(a,_,_,_,_) -> a) $ s
, schema . fmap (\(_,b,_,_,_) -> b) $ s
, schema . fmap (\(_,_,c,_,_) -> c) $ s
, schema . fmap (\(_,_,_,d,_) -> d) $ s
, schema . fmap (\(_,_,_,_,e) -> e) $ s
]
instance (JSONSchema a, JSONSchema b, JSONSchema c, JSONSchema d, JSONSchema e, JSONSchema f) => JSONSchema (a, b, c, d, e, f) where
schema s = Tuple
[ schema . fmap (\(a,_,_,_,_,_) -> a) $ s
, schema . fmap (\(_,b,_,_,_,_) -> b) $ s
, schema . fmap (\(_,_,c,_,_,_) -> c) $ s
, schema . fmap (\(_,_,_,d,_,_) -> d) $ s
, schema . fmap (\(_,_,_,_,e,_) -> e) $ s
, schema . fmap (\(_,_,_,_,_,f) -> f) $ s
]
instance (JSONSchema a, JSONSchema b, JSONSchema c, JSONSchema d, JSONSchema e, JSONSchema f, JSONSchema g) => JSONSchema (a, b, c, d, e, f, g) where
schema s = Tuple
[ schema . fmap (\(a,_,_,_,_,_,_) -> a) $ s
, schema . fmap (\(_,b,_,_,_,_,_) -> b) $ s
, schema . fmap (\(_,_,c,_,_,_,_) -> c) $ s
, schema . fmap (\(_,_,_,d,_,_,_) -> d) $ s
, schema . fmap (\(_,_,_,_,e,_,_) -> e) $ s
, schema . fmap (\(_,_,_,_,_,f,_) -> f) $ s
, schema . fmap (\(_,_,_,_,_,_,g) -> g) $ s
]
instance (JSONSchema a, JSONSchema b, JSONSchema c, JSONSchema d, JSONSchema e, JSONSchema f, JSONSchema g, JSONSchema h) => JSONSchema (a, b, c, d, e, f, g, h) where
schema s = Tuple
[ schema . fmap (\(a,_,_,_,_,_,_,_) -> a) $ s
, schema . fmap (\(_,b,_,_,_,_,_,_) -> b) $ s
, schema . fmap (\(_,_,c,_,_,_,_,_) -> c) $ s
, schema . fmap (\(_,_,_,d,_,_,_,_) -> d) $ s
, schema . fmap (\(_,_,_,_,e,_,_,_) -> e) $ s
, schema . fmap (\(_,_,_,_,_,f,_,_) -> f) $ s
, schema . fmap (\(_,_,_,_,_,_,g,_) -> g) $ s
, schema . fmap (\(_,_,_,_,_,_,_,h) -> h) $ s
]
instance (JSONSchema a, JSONSchema b, JSONSchema c, JSONSchema d, JSONSchema e, JSONSchema f, JSONSchema g, JSONSchema h, JSONSchema i) => JSONSchema (a, b, c, d, e, f, g, h, i) where
schema s = Tuple
[ schema . fmap (\(a,_,_,_,_,_,_,_,_) -> a) $ s
, schema . fmap (\(_,b,_,_,_,_,_,_,_) -> b) $ s
, schema . fmap (\(_,_,c,_,_,_,_,_,_) -> c) $ s
, schema . fmap (\(_,_,_,d,_,_,_,_,_) -> d) $ s
, schema . fmap (\(_,_,_,_,e,_,_,_,_) -> e) $ s
, schema . fmap (\(_,_,_,_,_,f,_,_,_) -> f) $ s
, schema . fmap (\(_,_,_,_,_,_,g,_,_) -> g) $ s
, schema . fmap (\(_,_,_,_,_,_,_,h,_) -> h) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,i) -> i) $ s
]
instance (JSONSchema a, JSONSchema b, JSONSchema c, JSONSchema d, JSONSchema e, JSONSchema f, JSONSchema g, JSONSchema h, JSONSchema i, JSONSchema j) => JSONSchema (a, b, c, d, e, f, g, h, i, j) where
schema s = Tuple
[ schema . fmap (\(a,_,_,_,_,_,_,_,_,_) -> a) $ s
, schema . fmap (\(_,b,_,_,_,_,_,_,_,_) -> b) $ s
, schema . fmap (\(_,_,c,_,_,_,_,_,_,_) -> c) $ s
, schema . fmap (\(_,_,_,d,_,_,_,_,_,_) -> d) $ s
, schema . fmap (\(_,_,_,_,e,_,_,_,_,_) -> e) $ s
, schema . fmap (\(_,_,_,_,_,f,_,_,_,_) -> f) $ s
, schema . fmap (\(_,_,_,_,_,_,g,_,_,_) -> g) $ s
, schema . fmap (\(_,_,_,_,_,_,_,h,_,_) -> h) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,i,_) -> i) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,j) -> j) $ s
]
instance (JSONSchema a, JSONSchema b, JSONSchema c, JSONSchema d, JSONSchema e, JSONSchema f, JSONSchema g, JSONSchema h, JSONSchema i, JSONSchema j, JSONSchema k) => JSONSchema (a, b, c, d, e, f, g, h, i, j, k) where
schema s = Tuple
[ schema . fmap (\(a,_,_,_,_,_,_,_,_,_,_) -> a) $ s
, schema . fmap (\(_,b,_,_,_,_,_,_,_,_,_) -> b) $ s
, schema . fmap (\(_,_,c,_,_,_,_,_,_,_,_) -> c) $ s
, schema . fmap (\(_,_,_,d,_,_,_,_,_,_,_) -> d) $ s
, schema . fmap (\(_,_,_,_,e,_,_,_,_,_,_) -> e) $ s
, schema . fmap (\(_,_,_,_,_,f,_,_,_,_,_) -> f) $ s
, schema . fmap (\(_,_,_,_,_,_,g,_,_,_,_) -> g) $ s
, schema . fmap (\(_,_,_,_,_,_,_,h,_,_,_) -> h) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,i,_,_) -> i) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,j,_) -> j) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,_,k) -> k) $ s
]
instance (JSONSchema a, JSONSchema b, JSONSchema c, JSONSchema d, JSONSchema e, JSONSchema f, JSONSchema g, JSONSchema h, JSONSchema i, JSONSchema j, JSONSchema k, JSONSchema l) => JSONSchema (a, b, c, d, e, f, g, h, i, j, k, l) where
schema s = Tuple
[ schema . fmap (\(a,_,_,_,_,_,_,_,_,_,_,_) -> a) $ s
, schema . fmap (\(_,b,_,_,_,_,_,_,_,_,_,_) -> b) $ s
, schema . fmap (\(_,_,c,_,_,_,_,_,_,_,_,_) -> c) $ s
, schema . fmap (\(_,_,_,d,_,_,_,_,_,_,_,_) -> d) $ s
, schema . fmap (\(_,_,_,_,e,_,_,_,_,_,_,_) -> e) $ s
, schema . fmap (\(_,_,_,_,_,f,_,_,_,_,_,_) -> f) $ s
, schema . fmap (\(_,_,_,_,_,_,g,_,_,_,_,_) -> g) $ s
, schema . fmap (\(_,_,_,_,_,_,_,h,_,_,_,_) -> h) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,i,_,_,_) -> i) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,j,_,_) -> j) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,_,k,_) -> k) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,_,_,l) -> l) $ s
]
instance (JSONSchema a, JSONSchema b, JSONSchema c, JSONSchema d, JSONSchema e, JSONSchema f, JSONSchema g, JSONSchema h, JSONSchema i, JSONSchema j, JSONSchema k, JSONSchema l, JSONSchema m) => JSONSchema (a, b, c, d, e, f, g, h, i, j, k, l, m) where
schema s = Tuple
[ schema . fmap (\(a,_,_,_,_,_,_,_,_,_,_,_,_) -> a) $ s
, schema . fmap (\(_,b,_,_,_,_,_,_,_,_,_,_,_) -> b) $ s
, schema . fmap (\(_,_,c,_,_,_,_,_,_,_,_,_,_) -> c) $ s
, schema . fmap (\(_,_,_,d,_,_,_,_,_,_,_,_,_) -> d) $ s
, schema . fmap (\(_,_,_,_,e,_,_,_,_,_,_,_,_) -> e) $ s
, schema . fmap (\(_,_,_,_,_,f,_,_,_,_,_,_,_) -> f) $ s
, schema . fmap (\(_,_,_,_,_,_,g,_,_,_,_,_,_) -> g) $ s
, schema . fmap (\(_,_,_,_,_,_,_,h,_,_,_,_,_) -> h) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,i,_,_,_,_) -> i) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,j,_,_,_) -> j) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,_,k,_,_) -> k) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,_,_,l,_) -> l) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,_,_,_,m) -> m) $ s
]
instance (JSONSchema a, JSONSchema b, JSONSchema c, JSONSchema d, JSONSchema e, JSONSchema f, JSONSchema g, JSONSchema h, JSONSchema i, JSONSchema j, JSONSchema k, JSONSchema l, JSONSchema m, JSONSchema n) => JSONSchema (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where
schema s = Tuple
[ schema . fmap (\(a,_,_,_,_,_,_,_,_,_,_,_,_,_) -> a) $ s
, schema . fmap (\(_,b,_,_,_,_,_,_,_,_,_,_,_,_) -> b) $ s
, schema . fmap (\(_,_,c,_,_,_,_,_,_,_,_,_,_,_) -> c) $ s
, schema . fmap (\(_,_,_,d,_,_,_,_,_,_,_,_,_,_) -> d) $ s
, schema . fmap (\(_,_,_,_,e,_,_,_,_,_,_,_,_,_) -> e) $ s
, schema . fmap (\(_,_,_,_,_,f,_,_,_,_,_,_,_,_) -> f) $ s
, schema . fmap (\(_,_,_,_,_,_,g,_,_,_,_,_,_,_) -> g) $ s
, schema . fmap (\(_,_,_,_,_,_,_,h,_,_,_,_,_,_) -> h) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,i,_,_,_,_,_) -> i) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,j,_,_,_,_) -> j) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,_,k,_,_,_) -> k) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,_,_,l,_,_) -> l) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,_,_,_,m,_) -> m) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,_,_,_,_,n) -> n) $ s
]
instance (JSONSchema a, JSONSchema b, JSONSchema c, JSONSchema d, JSONSchema e, JSONSchema f, JSONSchema g, JSONSchema h, JSONSchema i, JSONSchema j, JSONSchema k, JSONSchema l, JSONSchema m, JSONSchema n, JSONSchema o) => JSONSchema (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where
schema s = Tuple
[ schema . fmap (\(a,_,_,_,_,_,_,_,_,_,_,_,_,_,_) -> a) $ s
, schema . fmap (\(_,b,_,_,_,_,_,_,_,_,_,_,_,_,_) -> b) $ s
, schema . fmap (\(_,_,c,_,_,_,_,_,_,_,_,_,_,_,_) -> c) $ s
, schema . fmap (\(_,_,_,d,_,_,_,_,_,_,_,_,_,_,_) -> d) $ s
, schema . fmap (\(_,_,_,_,e,_,_,_,_,_,_,_,_,_,_) -> e) $ s
, schema . fmap (\(_,_,_,_,_,f,_,_,_,_,_,_,_,_,_) -> f) $ s
, schema . fmap (\(_,_,_,_,_,_,g,_,_,_,_,_,_,_,_) -> g) $ s
, schema . fmap (\(_,_,_,_,_,_,_,h,_,_,_,_,_,_,_) -> h) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,i,_,_,_,_,_,_) -> i) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,j,_,_,_,_,_) -> j) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,_,k,_,_,_,_) -> k) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,_,_,l,_,_,_) -> l) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,_,_,_,m,_,_) -> m) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,_,_,_,_,n,_) -> n) $ s
, schema . fmap (\(_,_,_,_,_,_,_,_,_,_,_,_,_,_,o) -> o) $ s
]