spotify-0.1.0.0: types/Spotify/Types/Internal/CustomJSON.hs
{-# LANGUAGE UndecidableInstances #-}
module Spotify.Types.Internal.CustomJSON where
import Data.Aeson (
FromJSON (parseJSON),
GFromJSON,
Options (constructorTagModifier, fieldLabelModifier),
Zero,
defaultOptions,
genericParseJSON,
)
import Data.Char (isUpper, toLower)
import Data.List (dropWhileEnd, stripPrefix)
import Data.Maybe (fromMaybe)
import GHC.Generics (Generic (Rep))
import Type.Reflection (Typeable, typeRep)
newtype CustomJSON a = CustomJSON a deriving (Generic)
instance (Generic a, GFromJSON Zero (Rep a), Typeable a) => FromJSON (CustomJSON a) where
parseJSON = fmap CustomJSON . genericParseJSON defaultOptions{constructorTagModifier, fieldLabelModifier}
where
fieldLabelModifier = camelToSnake . dropWhileEnd (== '_')
constructorTagModifier = camelToSnake . (fromMaybe <*> stripPrefix (show $ typeRep @a))
camelToSnake = \case
[] -> []
x : xs -> toLower x : go xs
where
go = \case
[] -> []
x : xs ->
if isUpper x
then '_' : toLower x : go xs
else x : go xs