module Conferer.Source.JSON
(
mkJsonSource
, mkJsonSource'
, traverseJSON
, resultToMaybe
, valueToText
, boolToString
)
where
import Data.Aeson
import qualified Data.HashMap.Strict as HashMap
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Text.Encoding as Text
import Data.Vector
import Text.Read (readMaybe)
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
import System.Directory (doesFileExist)
import Data.Monoid
import Conferer.Source.Files
import Conferer.Source.Null
import Conferer.Types
mkJsonSource :: SourceCreator
mkJsonSource config = do
fileToParse <- getFilePathFromEnv config "json"
fileExists <- doesFileExist fileToParse
if fileExists
then do
value <- decodeStrict' <$> B.readFile fileToParse
case value of
Nothing ->
error $ "Failed to decode file '" <> fileToParse <> "'"
Just v -> do
mkJsonSource' v config
else do
mkNullSource config
mkJsonSource' :: Value -> SourceCreator
mkJsonSource' v = \_config ->
return $ Source
{ getKeyInSource = \k -> do
return $ traverseJSON k v
}
traverseJSON :: Key -> Value -> Maybe Text
traverseJSON (Path []) v = valueToText v
traverseJSON (Path (k:ks)) (Object o) =
HashMap.lookup k o >>= traverseJSON (Path ks)
traverseJSON (Path (k:ks)) (Array vs) = do
n :: Int <- readMaybe $ Text.unpack k
value <- vs !? n
traverseJSON (Path ks) value
traverseJSON (Path _) _ = Nothing
valueToText :: Value -> Maybe Text
valueToText (String t) = Just t
valueToText (Object _o) = Nothing
valueToText (Array _as) = Nothing
valueToText (Number n) = Just $ Text.decodeUtf8 $ L.toStrict $ encode $ Number n
valueToText (Bool b) = Just $ boolToString b
valueToText (Null) = Nothing
boolToString :: Bool -> Text
boolToString True = "true"
boolToString False = "false"
resultToMaybe :: Result a -> Maybe a
resultToMaybe (Error _) = Nothing
resultToMaybe (Success a) = Just a