module Data.Aeson.Codec
(
JSONCodec
, ObjectParser, ObjectBuilder, ObjectCodec
, entry, pair, obj
) where
import Control.Applicative
import Data.Aeson
import Data.Aeson.Types (Parser, Pair)
import Control.Monad.Reader
import Control.Monad.Writer
import Data.Default.Class
import qualified Data.Text as T
import Data.String
import Data.Codec
type JSONCodec a = ConcreteCodec Value Parser a
instance (ToJSON a, FromJSON a) => Default (JSONCodec a) where
def = Codec (ReaderT parseJSON) (Const . toJSON)
type ObjectParser = ReaderT Object Parser
type ObjectBuilder = Const (Endo [ Pair ])
type ObjectCodec a = Codec ObjectParser ObjectBuilder a
pair :: ToJSON a => T.Text -> a -> ObjectBuilder ()
pair key val = Const $ Endo ((key .= val):)
entry :: T.Text -> JSONCodec a -> ObjectCodec a
entry key cd = Codec
{ parse = ReaderT $ \o -> (o .: key) >>= parseVal cd
, produce = pair key . produceVal cd
}
obj :: String -> ObjectCodec a -> JSONCodec a
obj err (Codec r w) = concrete
(withObject err $ runReaderT r)
(\x -> object $ appEndo (getConst $ w x) [])
instance (ToJSON a, FromJSON a) => IsString (ObjectCodec a) where
fromString s = entry (fromString s) def