{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module : Data.Aeson.Extra.SymTag -- Copyright : (C) 2015-2016 Oleg Grenrus -- License : BSD3 -- Maintainer : Oleg Grenrus -- module Data.Aeson.Extra.SingObject ( SingObject(..), mkSingObject, getSingObject, ) where import Prelude () import Prelude.Compat import Control.DeepSeq (NFData (..)) import Data.Aeson.Compat import Data.Proxy (Proxy (..)) import Data.Semigroup.Compat ((<>)) import Data.Typeable (Typeable) import GHC.TypeLits (KnownSymbol, Symbol, symbolVal) import qualified Data.Text as T #if MIN_VERSION_aeson(1,0,0) import Data.Aeson.Encoding (pair) import Data.Aeson.Internal (JSONPathElement (Key), ()) import Data.Aeson.Types hiding ((.:?)) import qualified Data.HashMap.Strict as HM #endif -- | Singleton value object -- -- > λ > decode "{\"value\": 42 }" :: Maybe (SingObject "value" Int) -- > Just (SingObject 42) -- -- > λ > encode (SingObject 42 :: SingObject "value" Int) -- > "{\"value\":42}" -- -- /Available with: base >=4.7/ newtype SingObject (s :: Symbol) a = SingObject a deriving (Eq, Ord, Show, Read, Functor, Foldable, Traversable, Typeable) mkSingObject :: Proxy s -> a -> SingObject s a mkSingObject _ = SingObject getSingObject :: Proxy s -> SingObject s a -> a getSingObject _ (SingObject x) = x #if MIN_VERSION_aeson(1,0,0) instance KnownSymbol s => FromJSON1 (SingObject s) where liftParseJSON p _ = withObject ("SingObject "<> show key) $ \obj -> case HM.lookup key obj of Nothing -> fail $ "key " ++ show key ++ " not present" Just v -> SingObject <$> p v Key key where key = T.pack $ symbolVal (Proxy :: Proxy s) instance KnownSymbol s => ToJSON1 (SingObject s) where liftToJSON to _ (SingObject x) = object [ key .= to x] where key = T.pack $ symbolVal (Proxy :: Proxy s) liftToEncoding to _ (SingObject x) = pairs $ pair key $ to x where key = T.pack $ symbolVal (Proxy :: Proxy s) instance (KnownSymbol s, FromJSON a) => FromJSON (SingObject s a) where parseJSON = parseJSON1 instance (KnownSymbol s, ToJSON a) => ToJSON (SingObject s a) where toJSON = toJSON1 toEncoding = toEncoding1 #else instance (KnownSymbol s, FromJSON a) => FromJSON (SingObject s a) where parseJSON = withObject ("SingObject "<> show key) $ \obj -> SingObject <$> obj .: T.pack key where key = symbolVal (Proxy :: Proxy s) instance (KnownSymbol s, ToJSON a) => ToJSON (SingObject s a) where #if MIN_VERSION_aeson(0,10,0) toEncoding (SingObject x) = pairs (T.pack key .= x) where key = symbolVal (Proxy :: Proxy s) #endif toJSON (SingObject x) = object [T.pack key .= x] where key = symbolVal (Proxy :: Proxy s) #endif -- | @since 0.4.1.0 instance NFData a => NFData (SingObject s a) where rnf (SingObject x) = rnf x