{-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE TupleSections #-} module Language.JsonGrammar.Serializer (serializeValue) where import Language.JsonGrammar.Grammar import Language.JsonGrammar.Util import Control.Applicative ((<$>), (<|>)) import Control.Monad ((>=>)) import qualified Data.Aeson as Ae import qualified Data.HashMap.Strict as H import qualified Data.Vector as V -- | Convert a 'Grammar' to a JSON serializer. serializeValue :: Grammar 'Val t1 t2 -> t2 -> Maybe t1 serializeValue = \case Id -> return g1 :. g2 -> serializeValue g1 >=> serializeValue g2 Empty -> fail "empty grammar" g1 :<> g2 -> \x -> serializeValue g1 x <|> serializeValue g2 x Pure _ f -> f Many g -> manyM (serializeValue g) Literal val -> return . (val :-) Label _ g -> serializeValue g Object g -> \x -> do (obj, y) <- serializeProperties g (H.empty, x) return (Ae.Object obj :- y) Array g -> \x -> do (arr, y) <- serializeElements g (V.empty, x) return (Ae.Array arr :- y) Coerce _ g -> serializeValue g serializeProperties :: Grammar 'Obj t1 t2 -> (Ae.Object, t2) -> Maybe (Ae.Object, t1) serializeProperties = \case Id -> return g1 :. g2 -> serializeProperties g1 >=> serializeProperties g2 Empty -> fail "empty grammar" g1 :<> g2 -> \objx -> serializeProperties g1 objx <|> serializeProperties g2 objx Pure _ f -> \(obj, x) -> (obj, ) <$> f x Many g -> manyM (serializeProperties g) Property n g -> \(obj, x) -> do val :- y <- serializeValue g x return (H.insert n val obj, y) serializeElements :: Grammar 'Arr t1 t2 -> (Ae.Array, t2) -> Maybe (Ae.Array, t1) serializeElements = \case Id -> return g1 :. g2 -> serializeElements g1 >=> serializeElements g2 Empty -> fail "empty grammar" g1 :<> g2 -> \x -> serializeElements g1 x <|> serializeElements g2 x Pure _ f -> \(arr, x) -> (arr, ) <$> f x Many g -> manyM (serializeElements g) Element g -> \(arr, x) -> do val :- y <- serializeValue g x return (V.snoc arr val, y)