language-conf-0.2.1.0: src/Data/Conf/Aeson.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeSynonymInstances #-}
module Data.Conf.Aeson
where
import Control.Monad
import Data.Aeson
import Data.Aeson
import Data.Aeson.Types
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Scientific as Scientific
import Data.String
import qualified Data.Text as Text
import qualified Data.Vector as Vector
import Data.Conf.PrettyPrint
import Data.Conf.Types
fromToJSON :: ToJSON a => a -> Result Conf
fromToJSON = fromJSON . toJSON
instance FromJSON Conf where
parseJSON (Object obj) = do
let oList = HashMap.toList obj
forM oList $ \(k, v) ->
case v of
o@(Object _) -> do
cs <- parseJSON o
return $ ConfStatementBlock (Block (Text.words k) cs)
(Array vs) -> return $
ConfStatementExpression (Expression k (map toExpressionValue (Vector.toList vs)))
value -> return $
ConfStatementExpression (Expression k [toExpressionValue value])
where
toExpressionValue (Number oc) =
case Scientific.floatingOrInteger oc of
Left f -> fromString (show (f :: Double))
Right i -> fromString (show (i :: Integer))
toExpressionValue (String oc) = oc
toExpressionValue (Bool b) = if b then "true" else "false"
toExpressionValue _ = error "Invalid type"
parseJSON invalid = typeMismatch "Conf" invalid
instance ToJSON Conf where
toJSON cs = object ps
where
ps = concatMap toPair cs
toPair (ConfStatementExpression (Expression e [v])) = [ e .= String v ]
toPair (ConfStatementExpression (Expression e vs)) = [ e .= toJSON vs ]
toPair (ConfStatementBlock (Block [k] css)) = [ k .= toJSON css ]
toPair (ConfStatementBlock (Block ks css)) = [ Text.unwords ks .= toJSON css ]
toPair ConfStatementEmptyLine = []
toPair (ConfStatementComment _) = []