factual-api-0.5.0: Data/Factual/Response.hs
-- | 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 = fromJust $ 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