packages feed

gogol-core-1.0.0.0: src/Gogol/Data/JSON.hs

{-# LANGUAGE CPP #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}

-- |
-- Module      : Gogol.Data.JSON
-- Copyright   : (c) 2015-2022 Brendan Hay <brendan.g.hay@gmail.com>
-- License     : Mozilla Public License, v. 2.0.
-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
-- Stability   : provisional
-- Portability : non-portable (GHC extensions)
module Gogol.Data.JSON
  ( Value,
    AsText (..),
    parseJSONObject,
    parseJSONText,
    toJSONText,

    -- * Re-exports
    FromJSON (..),
    FromJSONKey (..),
    ToJSON (..),
    ToJSONKey (..),
    withObject,
    emptyObject,
    object,
    (.=),
    (.:),
    (.:?),
    (.!=),
  )
where

import Data.Aeson
import Data.Aeson.Types
import Data.Text qualified as Text
import Web.HttpApiData (FromHttpApiData (..), ToHttpApiData (..))

#if MIN_VERSION_aeson(2,0,0)
import Data.Aeson.KeyMap (KeyMap)
#else
import Data.HashMap.Strict (HashMap)
import Data.Text (Text)
#endif

newtype AsText a = AsText {fromAsText :: a}
  deriving (Eq, Ord, Read, Show, Num, Fractional, ToHttpApiData, FromHttpApiData)

instance (FromJSON a, FromHttpApiData a) => FromJSON (AsText a) where
  parseJSON (String s) = either (fail . Text.unpack) (pure . AsText) (parseQueryParam s)
  parseJSON o = AsText <$> parseJSON o

instance (ToHttpApiData a) => ToJSON (AsText a) where
  toJSON (AsText x) = String (toQueryParam x)

#if MIN_VERSION_aeson(2,0,0)
parseJSONObject :: FromJSON a => KeyMap Value -> Parser a
#else
parseJSONObject :: FromJSON a => HashMap Text Value -> Parser a
#endif
parseJSONObject = parseJSON . toJSON

parseJSONText :: (FromHttpApiData a) => String -> Value -> Parser a
parseJSONText n = withText n (either (fail . f) pure . parseQueryParam)
  where
    f x = n ++ " - " ++ Text.unpack x

toJSONText :: (ToHttpApiData a) => a -> Value
toJSONText = String . toQueryParam