{-# LANGUAGE CPP #-}

-- |
-- Module      : Amazonka.Data.JSON
-- Copyright   : (c) 2013-2021 Brendan Hay
-- License     : Mozilla Public License, v. 2.0.
-- Maintainer  : Brendan Hay <brendan.g.hay+amazonka@gmail.com>
-- Stability   : provisional
-- Portability : non-portable (GHC extensions)
module Amazonka.Data.JSON
  ( -- * FromJSON
    Aeson.FromJSON (..),
    Aeson.FromJSONKey (..),
    parseJSONText,
    Aeson.eitherDecode,
    Aeson.eitherDecode',

    -- ** Parser a
    Aeson.withObject,
    (Aeson..:),
    (Aeson..:?),
    (Aeson..!=),

    -- ** Either String a
    eitherParseJSON,
    (.:>),
    (.?>),

    -- * ToJSON
    Aeson.ToJSON (..),
    Aeson.ToJSONKey (..),
    toJSONText,
    Aeson.Value (Object),
    Aeson.object,
    (Aeson..=),
  )
where

import Amazonka.Data.Text
import Amazonka.Prelude
import qualified Data.Aeson as Aeson
import qualified Data.Aeson.Types as Aeson.Types

#if MIN_VERSION_aeson(2,0,0)
import qualified Data.Aeson.KeyMap as KM
import Data.Aeson.Key (Key)
#else
import qualified Data.HashMap.Strict as KM
type Key = Text
#endif

parseJSONText :: FromText a => String -> Aeson.Value -> Aeson.Types.Parser a
parseJSONText :: String -> Value -> Parser a
parseJSONText String
n = String -> (Text -> Parser a) -> Value -> Parser a
forall a. String -> (Text -> Parser a) -> Value -> Parser a
Aeson.withText String
n ((String -> Parser a)
-> (a -> Parser a) -> Either String a -> Parser a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either String a -> Parser a)
-> (Text -> Either String a) -> Text -> Parser a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either String a
forall a. FromText a => Text -> Either String a
fromText)

toJSONText :: ToText a => a -> Aeson.Value
toJSONText :: a -> Value
toJSONText = Text -> Value
Aeson.String (Text -> Value) -> (a -> Text) -> a -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Text
forall a. ToText a => a -> Text
toText

eitherParseJSON :: Aeson.FromJSON a => Aeson.Object -> Either String a
eitherParseJSON :: Object -> Either String a
eitherParseJSON = (Value -> Parser a) -> Value -> Either String a
forall a b. (a -> Parser b) -> a -> Either String b
Aeson.Types.parseEither Value -> Parser a
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Value -> Either String a)
-> (Object -> Value) -> Object -> Either String a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Object -> Value
Aeson.Object

(.:>) :: Aeson.FromJSON a => Aeson.Object -> Key -> Either String a
.:> :: Object -> Text -> Either String a
(.:>) Object
o Text
k =
  case Text -> Object -> Maybe Value
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
KM.lookup Text
k Object
o of
    Maybe Value
Nothing -> String -> Either String a
forall a b. a -> Either a b
Left (String -> Either String a) -> String -> Either String a
forall a b. (a -> b) -> a -> b
$ String
"key " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
forall a. Show a => a -> String
show Text
k String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" not present"
    Just Value
v -> (Value -> Parser a) -> Value -> Either String a
forall a b. (a -> Parser b) -> a -> Either String b
Aeson.Types.parseEither Value -> Parser a
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON Value
v

(.?>) :: Aeson.FromJSON a => Aeson.Object -> Key -> Either String (Maybe a)
.?> :: Object -> Text -> Either String (Maybe a)
(.?>) Object
o Text
k =
  case Text -> Object -> Maybe Value
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
KM.lookup Text
k Object
o of
    Maybe Value
Nothing -> Maybe a -> Either String (Maybe a)
forall a b. b -> Either a b
Right Maybe a
forall a. Maybe a
Nothing
    Just Value
v -> (Value -> Parser (Maybe a)) -> Value -> Either String (Maybe a)
forall a b. (a -> Parser b) -> a -> Either String b
Aeson.Types.parseEither Value -> Parser (Maybe a)
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON Value
v