{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} module Web.VKHS.API.Aeson ( api , api' , module Web.VKHS.API.Types ) where import Control.Applicative import Control.Monad import Control.Monad.Trans import Control.Monad.Writer import Control.Monad.Error import Data.Aeson as A import qualified Data.Aeson.Types as A import Data.Aeson (FromJSON, (.:), (.:?)) import Data.Aeson.Generic as AG import Data.ByteString.Lazy as BS import Data.Typeable import Data.Data import Data.Vector as V (head, tail, toList) import Web.VKHS.Types import Web.VKHS.API.Types import qualified Web.VKHS.API as Base instance (FromJSON a) => FromJSON (Response a) where parseJSON (A.Object v) = do a <- v .: "response" x <- A.parseJSON a return (Response x) parseGeneric a = case AG.fromJSON a of A.Success a -> return a A.Error s -> fail $ "parseGeneric fails:" ++ s instance FromJSON MusicRecord where parseJSON = parseGeneric instance FromJSON WallRecord where parseJSON (Object o) = WR <$> (o .: "id") <*> (o .: "to_id") <*> (o .: "from_id") <*> (o .: "text") <*> (o .: "date") instance (FromJSON a) => FromJSON (SizedList [a]) where parseJSON (A.Array v) = do n <- A.parseJSON (V.head v) t <- A.parseJSON (A.Array (V.tail v)) return (SL n t) api' :: (A.FromJSON a) => Env CallEnv -> String -> [(String,String)] -> IO (Either String a) api' e mn mp = runErrorT $ do e <- ErrorT (Base.api e mn mp) let check (Just x) = return x check (Nothing) = fail $ "AESON: error parsing JSON: " ++ show e check $ A.decode $ BS.fromStrict e api :: Env CallEnv -> String -> [(String,String)] -> IO (Either String A.Value) api = api'