{-# LANGUAGE OverloadedStrings #-} module Eventful.Store.DynamoDB.DynamoJSON ( valueToAttributeValue , attributeValueToValue ) where import Control.Lens import Data.Aeson import qualified Data.HashMap.Strict as HM import qualified Data.Text as T import qualified Data.Vector as V import Network.AWS.DynamoDB hiding (Null) -- | Note, currently we can't properly disambiguate between an empty Object or -- an empty Array because of amazonka's 'AttributeValue' lenses. We use a very -- nasty kludge where we replace empty Objects with a string with a very -- special value. Follow this issue to see when we can remove the kludge: -- https://github.com/brendanhay/amazonka/issues/282. valueToAttributeValue :: Value -> AttributeValue valueToAttributeValue (String v) = attributeValue & avS ?~ v valueToAttributeValue (Number v) = attributeValue & avN ?~ T.pack (show v) valueToAttributeValue (Bool v) = attributeValue & avBOOL ?~ v valueToAttributeValue (Array vs) = attributeValue & avL .~ fmap valueToAttributeValue (V.toList vs) valueToAttributeValue (Object v) | HM.null v = attributeValue & avS ?~ "__eventful-dynamodb-empty-object__" | otherwise = attributeValue & avM .~ fmap valueToAttributeValue v valueToAttributeValue Null = attributeValue & avNULL ?~ True attributeValueToValue :: AttributeValue -> Value attributeValueToValue av | Just "__eventful-dynamodb-empty-object__" <- av ^. avS = Object HM.empty | Just v <- av ^. avS = String v | Just v <- av ^. avN = Number $ read $ T.unpack v | Just v <- av ^. avBOOL = Bool v | Just _ <- av ^. avNULL = Null | v <- av ^. avM, not (HM.null v) = Object $ fmap attributeValueToValue v | vs <- av ^. avL = Array $ V.fromList $ fmap attributeValueToValue vs | otherwise = Null