packages feed

extensible-0.3.4: examples/aeson.hs

{-# LANGUAGE TypeOperators, DataKinds, FlexibleContexts, FlexibleInstances, UndecidableInstances, PolyKinds, TemplateHaskell #-}
import Data.Aeson (FromJSON(..), withObject)
import Data.Extensible (Record, Field(..), KeyValue, AssocKey, Forall, hgenerateFor)
import GHC.TypeLits (KnownSymbol, symbolVal)
import Data.Proxy
import Data.String (fromString)
import qualified Data.HashMap.Strict as HM

keyProxy :: proxy kv -> Proxy (AssocKey kv)
keyProxy _ = Proxy

instance Forall (KeyValue KnownSymbol FromJSON) xs => FromJSON (Record xs) where
  parseJSON = withObject "Object" $ \v -> hgenerateFor (Proxy :: Proxy (KeyValue KnownSymbol FromJSON))
    $ \m -> let k = symbolVal (keyProxy m) in case HM.lookup (fromString k) v of
      Just a -> Field <$> return <$> parseJSON a
      Nothing -> fail $ "Missing key: " ++ k