{-# LANGUAGE TupleSections #-}
module Serokell.Data.Variant.Serialization
(
) where
import Universum
import Data.Scientific (floatingOrInteger)
import Formatting (build, sformat)
import Serokell.Data.Variant.Variant (VarMap, Variant (..))
import Serokell.Util.Base64 (JsonByteString (JsonByteString))
import qualified Data.Aeson as Aeson
import qualified Data.HashMap.Strict as HM
varMapToObject :: VarMap -> Aeson.Object
varMapToObject =
HM.fromList . map (bimap (sformat build) Aeson.toJSON) . toPairs
instance Aeson.ToJSON Variant where
toJSON VarNone = Aeson.Null
toJSON (VarBool v) = Aeson.toJSON v
toJSON (VarInt v) = Aeson.toJSON v
toJSON (VarUInt v) = Aeson.toJSON v
toJSON (VarFloat v) = Aeson.toJSON v
toJSON (VarBytes v) = Aeson.toJSON . JsonByteString $ v
toJSON (VarString v) = Aeson.toJSON v
toJSON (VarList v) = Aeson.toJSON v
toJSON (VarMap v) = Aeson.Object . varMapToObject $ v
toEncoding VarNone = Aeson.toEncoding Aeson.Null
toEncoding (VarBool v) = Aeson.toEncoding v
toEncoding (VarInt v) = Aeson.toEncoding v
toEncoding (VarUInt v) = Aeson.toEncoding v
toEncoding (VarFloat v) = Aeson.toEncoding v
toEncoding (VarBytes v) = Aeson.toEncoding . JsonByteString $ v
toEncoding (VarString v) = Aeson.toEncoding v
toEncoding (VarList v) = Aeson.toEncoding v
toEncoding (VarMap v) = Aeson.toEncoding . varMapToObject $ v
instance Aeson.FromJSON Variant where
parseJSON Aeson.Null = pure VarNone
parseJSON (Aeson.Bool v) = pure . VarBool $ v
parseJSON (Aeson.Number v) =
pure . either VarFloat convertInt . floatingOrInteger $ v
where
convertInt :: Integer -> Variant
convertInt i
| i < 0 = VarInt $ fromIntegral i
| otherwise = VarUInt $ fromIntegral i
parseJSON (Aeson.String v) = pure . VarString $ v
parseJSON (Aeson.Array v) = fmap VarList . mapM Aeson.parseJSON $ v
parseJSON (Aeson.Object v) =
fmap (VarMap . HM.fromList) .
mapM
(\(key,val) ->
(VarString key, ) <$> Aeson.parseJSON val) .
toPairs $
v