-- | This module exports the type which encapsulates Factual API responses. It -- also provides some utility function that can be used to manipulate the -- Aeson object which holds the data. module Data.Factual.Response ( -- * Response type Response(..) -- * Utility functions , fromValue , toList , lookupNumber , lookupString , lookupValue , lookupValueSafe -- * Aeson Value type , Value ) where import Data.Maybe (fromJust) import Data.Aeson import Data.Attoparsec.Number import qualified Data.HashMap.Lazy as L import qualified Data.Text as T import qualified Data.Vector as V import Debug.Trace -- | A response object has a status (that will be ok if the query was successful -- and error if the query failed), a version (which should always be 3.0) and -- the actual response data which is an Aeson value. data Response = Response { status :: String , version :: Double , response :: Value , errorMessage :: Maybe String , errorType :: Maybe String } deriving (Eq, Show) -- | This function is used by the API module to turn the Aeson value returned by -- the API into a Response value. fromValue :: Value -> Response fromValue value | respStatus == "ok" = formValidResponse value | otherwise = formErrorResponse value where respStatus = lookupString "status" value -- | This function can be used to convert an Aeson Array value into a vanilla -- list. toList :: Value -> [Value] toList (Array a) = V.toList a toList v = [v] -- | This function can be used to extract a Double from an Aeson Object -- (HashMap) value. lookupNumber :: String -> Value -> Double lookupNumber key hashmap = extractNumber $ lookupValue key hashmap -- | This function can be used to extract a String from an Aeson Object -- (HashMap) value. lookupString :: String -> Value -> String lookupString key hashmap = extractString $ lookupValue key hashmap -- | This function can be used to extract any Aeson value from an Aeson Object -- (HashMap) value. lookupValue :: String -> Value -> Value lookupValue key hashmap = if maybeValue == Nothing then Null else fromJust maybeValue where maybeValue = lookupValueSafe key hashmap -- | This function can be used to safely extract any Aeson value from an Aeson -- Object (HashMap) value. lookupValueSafe :: String -> Value -> Maybe Value lookupValueSafe key (Object x) = L.lookup (T.pack key) x -- The following helper functions aid the lookup functions. formErrorResponse :: Value -> Response formErrorResponse value = Response { status = lookupString "status" value , version = lookupNumber "version" value , response = Null , errorMessage = Just $ lookupString "message" value , errorType = Just $ lookupString "error_type" value } formValidResponse :: Value -> Response formValidResponse value = Response { status = "ok" , version = lookupNumber "version" value , response = lookupValue "response" value , errorMessage = Nothing , errorType = Nothing } extractString :: Value -> String extractString (String x) = T.unpack x extractNumber :: Value -> Double extractNumber (Number x) = toDouble x toDouble :: Number -> Double toDouble (I x) = fromIntegral x toDouble (D x) = x