{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- |
-- Module:      Data.Aeson
-- Copyright:   (c) 2011-2016 Bryan O'Sullivan
--              (c) 2011 MailRank, Inc.
-- License:     BSD3
-- Maintainer:  Bryan O'Sullivan <bos@serpentine.com>
-- Stability:   experimental
-- Portability: portable
--
-- Types and functions for working efficiently with JSON data.
--
-- (A note on naming: in Greek mythology, Aeson was the father of Jason.)

module Data.Aeson
    (
    -- * How to use this library
    -- $use

    -- ** Writing instances by hand
    -- $manual

    -- ** Working with the AST
    -- $ast

    -- ** Decoding to a Haskell value
    -- $haskell

    -- ** Decoding a mixed-type object
    -- $mixed

    -- * Encoding and decoding
    -- $encoding_and_decoding

    -- ** Direct encoding
    -- $encoding

    -- * Remarks on specific encodings
    -- ** Time
    -- $time

    -- * Main encoding and decoding functions
      decode
    , decode'
    , eitherDecode
    , eitherDecode'
    , encode
    , encodeFile
    -- ** Variants for strict bytestrings
    , decodeStrict
    , decodeFileStrict
    , decodeStrict'
    , decodeFileStrict'
    , eitherDecodeStrict
    , eitherDecodeFileStrict
    , eitherDecodeStrict'
    , eitherDecodeFileStrict'
    -- ** Exception throwing variants
    , AesonException (..)
    , throwDecode
    , throwDecodeStrict
    , throwDecode'
    , throwDecodeStrict'
    -- * Core JSON types
    , Value(..)
    , Encoding
    , fromEncoding
    , Array
    , Object
    , Key
    -- * Convenience types
    , DotNetTime(..)
    -- * Type conversion
    , FromJSON(..)
    , Result(..)
    , fromJSON
    , ToJSON(..)
    , KeyValue(..)
    , (<?>)
    , JSONPath
    -- ** Keys for maps
    , ToJSONKey(..)
    , ToJSONKeyFunction(..)
    , FromJSONKey(..)
    , FromJSONKeyFunction(..)
    -- *** Generic keys
    , GToJSONKey()
    , genericToJSONKey
    , GFromJSONKey()
    , genericFromJSONKey
    -- ** Liftings to unary and binary type constructors
    , FromJSON1(..)
    , parseJSON1
    , FromJSON2(..)
    , parseJSON2
    , ToJSON1(..)
    , toJSON1
    , toEncoding1
    , ToJSON2(..)
    , toJSON2
    , toEncoding2
    -- ** Generic JSON classes and options
    , GFromJSON
    , FromArgs
    , GToJSON
    , GToEncoding
    , GToJSON'
    , ToArgs
    , Zero
    , One
    , genericToJSON
    , genericLiftToJSON
    , genericToEncoding
    , genericLiftToEncoding
    , genericParseJSON
    , genericLiftParseJSON
    -- ** Generic and TH encoding configuration
    , Options
    , defaultOptions
    -- *** Options fields
    -- $optionsFields
    , fieldLabelModifier
    , constructorTagModifier
    , allNullaryToStringTag
    , omitNothingFields
    , sumEncoding
    , unwrapUnaryRecords
    , tagSingleConstructors
    , rejectUnknownFields
    -- *** Options utilities
    , SumEncoding(..)
    , camelTo2
    , defaultTaggedObject
    -- ** Options for object keys
    , JSONKeyOptions
    , keyModifier
    , defaultJSONKeyOptions

    -- * Inspecting @'Value's@
    , withObject
    , withText
    , withArray
    , withScientific
    , withBool
    , withEmbeddedJSON
    -- * Constructors and accessors
    , Series
    , pairs
    , foldable
    , (.:)
    , (.:?)
    , (.:!)
    , (.!=)
    , object
    -- * Parsing
    , json
    , json'
    , parseIndexedJSON
    ) where

import Prelude.Compat

import Control.Exception (Exception (..))
import Control.Monad.Catch (MonadThrow (..))
import Data.Aeson.Types.FromJSON (ifromJSON, parseIndexedJSON)
import Data.Aeson.Encoding (encodingToLazyByteString)
import Data.Aeson.Parser.Internal (decodeWith, decodeStrictWith, eitherDecodeWith, eitherDecodeStrictWith, jsonEOF, json, jsonEOF', json')
import Data.Aeson.Types
import Data.Aeson.Types.Internal (formatError)
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L

-- $setup
-- >>> :set -XOverloadedStrings

-- | Efficiently serialize a JSON value as a lazy 'L.ByteString'.
--
-- This is implemented in terms of the 'ToJSON' class's 'toEncoding' method.
encode :: (ToJSON a) => a -> L.ByteString
encode :: forall a. ToJSON a => a -> ByteString
encode = Encoding' Value -> ByteString
forall a. Encoding' a -> ByteString
encodingToLazyByteString (Encoding' Value -> ByteString)
-> (a -> Encoding' Value) -> a -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Encoding' Value
forall a. ToJSON a => a -> Encoding' Value
toEncoding

-- | Efficiently serialize a JSON value as a lazy 'L.ByteString' and write it to a file.
encodeFile :: (ToJSON a) => FilePath -> a -> IO ()
encodeFile :: forall a. ToJSON a => FilePath -> a -> IO ()
encodeFile FilePath
fp = FilePath -> ByteString -> IO ()
L.writeFile FilePath
fp (ByteString -> IO ()) -> (a -> ByteString) -> a -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> ByteString
forall a. ToJSON a => a -> ByteString
encode

-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
-- If this fails due to incomplete or invalid input, 'Nothing' is
-- returned.
--
-- The input must consist solely of a JSON document, with no trailing
-- data except for whitespace.
--
-- This function parses immediately, but defers conversion.  See
-- 'json' for details.
decode :: (FromJSON a) => L.ByteString -> Maybe a
decode :: forall a. FromJSON a => ByteString -> Maybe a
decode = Parser Value -> (Value -> Result a) -> ByteString -> Maybe a
forall a.
Parser Value -> (Value -> Result a) -> ByteString -> Maybe a
decodeWith Parser Value
jsonEOF Value -> Result a
forall a. FromJSON a => Value -> Result a
fromJSON
{-# INLINE decode #-}

-- | Efficiently deserialize a JSON value from a strict 'B.ByteString'.
-- If this fails due to incomplete or invalid input, 'Nothing' is
-- returned.
--
-- The input must consist solely of a JSON document, with no trailing
-- data except for whitespace.
--
-- This function parses immediately, but defers conversion.  See
-- 'json' for details.
decodeStrict :: (FromJSON a) => B.ByteString -> Maybe a
decodeStrict :: forall a. FromJSON a => ByteString -> Maybe a
decodeStrict = Parser Value -> (Value -> Result a) -> ByteString -> Maybe a
forall a.
Parser Value -> (Value -> Result a) -> ByteString -> Maybe a
decodeStrictWith Parser Value
jsonEOF Value -> Result a
forall a. FromJSON a => Value -> Result a
fromJSON
{-# INLINE decodeStrict #-}

-- | Efficiently deserialize a JSON value from a file.
-- If this fails due to incomplete or invalid input, 'Nothing' is
-- returned.
--
-- The input file's content must consist solely of a JSON document,
-- with no trailing data except for whitespace.
--
-- This function parses immediately, but defers conversion.  See
-- 'json' for details.
decodeFileStrict :: (FromJSON a) => FilePath -> IO (Maybe a)
decodeFileStrict :: forall a. FromJSON a => FilePath -> IO (Maybe a)
decodeFileStrict = (ByteString -> Maybe a) -> IO ByteString -> IO (Maybe a)
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> Maybe a
forall a. FromJSON a => ByteString -> Maybe a
decodeStrict (IO ByteString -> IO (Maybe a))
-> (FilePath -> IO ByteString) -> FilePath -> IO (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO ByteString
B.readFile

-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
-- If this fails due to incomplete or invalid input, 'Nothing' is
-- returned.
--
-- The input must consist solely of a JSON document, with no trailing
-- data except for whitespace.
--
-- This function parses and performs conversion immediately.  See
-- 'json'' for details.
decode' :: (FromJSON a) => L.ByteString -> Maybe a
decode' :: forall a. FromJSON a => ByteString -> Maybe a
decode' = Parser Value -> (Value -> Result a) -> ByteString -> Maybe a
forall a.
Parser Value -> (Value -> Result a) -> ByteString -> Maybe a
decodeWith Parser Value
jsonEOF' Value -> Result a
forall a. FromJSON a => Value -> Result a
fromJSON
{-# INLINE decode' #-}

-- | Efficiently deserialize a JSON value from a strict 'B.ByteString'.
-- If this fails due to incomplete or invalid input, 'Nothing' is
-- returned.
--
-- The input must consist solely of a JSON document, with no trailing
-- data except for whitespace.
--
-- This function parses and performs conversion immediately.  See
-- 'json'' for details.
decodeStrict' :: (FromJSON a) => B.ByteString -> Maybe a
decodeStrict' :: forall a. FromJSON a => ByteString -> Maybe a
decodeStrict' = Parser Value -> (Value -> Result a) -> ByteString -> Maybe a
forall a.
Parser Value -> (Value -> Result a) -> ByteString -> Maybe a
decodeStrictWith Parser Value
jsonEOF' Value -> Result a
forall a. FromJSON a => Value -> Result a
fromJSON
{-# INLINE decodeStrict' #-}

-- | Efficiently deserialize a JSON value from a file.
-- If this fails due to incomplete or invalid input, 'Nothing' is
-- returned.
--
-- The input file's content must consist solely of a JSON document,
-- with no trailing data except for whitespace.
--
-- This function parses and performs conversion immediately.  See
-- 'json'' for details.
decodeFileStrict' :: (FromJSON a) => FilePath -> IO (Maybe a)
decodeFileStrict' :: forall a. FromJSON a => FilePath -> IO (Maybe a)
decodeFileStrict' = (ByteString -> Maybe a) -> IO ByteString -> IO (Maybe a)
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> Maybe a
forall a. FromJSON a => ByteString -> Maybe a
decodeStrict' (IO ByteString -> IO (Maybe a))
-> (FilePath -> IO ByteString) -> FilePath -> IO (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO ByteString
B.readFile

eitherFormatError :: Either (JSONPath, String) a -> Either String a
eitherFormatError :: forall a. Either (JSONPath, FilePath) a -> Either FilePath a
eitherFormatError = ((JSONPath, FilePath) -> Either FilePath a)
-> (a -> Either FilePath a)
-> Either (JSONPath, FilePath) a
-> Either FilePath a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (FilePath -> Either FilePath a
forall a b. a -> Either a b
Left (FilePath -> Either FilePath a)
-> ((JSONPath, FilePath) -> FilePath)
-> (JSONPath, FilePath)
-> Either FilePath a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (JSONPath -> FilePath -> FilePath)
-> (JSONPath, FilePath) -> FilePath
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry JSONPath -> FilePath -> FilePath
formatError) a -> Either FilePath a
forall a b. b -> Either a b
Right
{-# INLINE eitherFormatError #-}

-- | Like 'decode' but returns an error message when decoding fails.
eitherDecode :: (FromJSON a) => L.ByteString -> Either String a
eitherDecode :: forall a. FromJSON a => ByteString -> Either FilePath a
eitherDecode = Either (JSONPath, FilePath) a -> Either FilePath a
forall a. Either (JSONPath, FilePath) a -> Either FilePath a
eitherFormatError (Either (JSONPath, FilePath) a -> Either FilePath a)
-> (ByteString -> Either (JSONPath, FilePath) a)
-> ByteString
-> Either FilePath a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser Value
-> (Value -> IResult a)
-> ByteString
-> Either (JSONPath, FilePath) a
forall a.
Parser Value
-> (Value -> IResult a)
-> ByteString
-> Either (JSONPath, FilePath) a
eitherDecodeWith Parser Value
jsonEOF Value -> IResult a
forall a. FromJSON a => Value -> IResult a
ifromJSON
{-# INLINE eitherDecode #-}

-- | Like 'decodeStrict' but returns an error message when decoding fails.
eitherDecodeStrict :: (FromJSON a) => B.ByteString -> Either String a
eitherDecodeStrict :: forall a. FromJSON a => ByteString -> Either FilePath a
eitherDecodeStrict =
  Either (JSONPath, FilePath) a -> Either FilePath a
forall a. Either (JSONPath, FilePath) a -> Either FilePath a
eitherFormatError (Either (JSONPath, FilePath) a -> Either FilePath a)
-> (ByteString -> Either (JSONPath, FilePath) a)
-> ByteString
-> Either FilePath a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser Value
-> (Value -> IResult a)
-> ByteString
-> Either (JSONPath, FilePath) a
forall a.
Parser Value
-> (Value -> IResult a)
-> ByteString
-> Either (JSONPath, FilePath) a
eitherDecodeStrictWith Parser Value
jsonEOF Value -> IResult a
forall a. FromJSON a => Value -> IResult a
ifromJSON
{-# INLINE eitherDecodeStrict #-}

-- | Like 'decodeFileStrict' but returns an error message when decoding fails.
eitherDecodeFileStrict :: (FromJSON a) => FilePath -> IO (Either String a)
eitherDecodeFileStrict :: forall a. FromJSON a => FilePath -> IO (Either FilePath a)
eitherDecodeFileStrict =
  (ByteString -> Either FilePath a)
-> IO ByteString -> IO (Either FilePath a)
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> Either FilePath a
forall a. FromJSON a => ByteString -> Either FilePath a
eitherDecodeStrict (IO ByteString -> IO (Either FilePath a))
-> (FilePath -> IO ByteString)
-> FilePath
-> IO (Either FilePath a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO ByteString
B.readFile
{-# INLINE eitherDecodeFileStrict #-}

-- | Like 'decode'' but returns an error message when decoding fails.
eitherDecode' :: (FromJSON a) => L.ByteString -> Either String a
eitherDecode' :: forall a. FromJSON a => ByteString -> Either FilePath a
eitherDecode' = Either (JSONPath, FilePath) a -> Either FilePath a
forall a. Either (JSONPath, FilePath) a -> Either FilePath a
eitherFormatError (Either (JSONPath, FilePath) a -> Either FilePath a)
-> (ByteString -> Either (JSONPath, FilePath) a)
-> ByteString
-> Either FilePath a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser Value
-> (Value -> IResult a)
-> ByteString
-> Either (JSONPath, FilePath) a
forall a.
Parser Value
-> (Value -> IResult a)
-> ByteString
-> Either (JSONPath, FilePath) a
eitherDecodeWith Parser Value
jsonEOF' Value -> IResult a
forall a. FromJSON a => Value -> IResult a
ifromJSON
{-# INLINE eitherDecode' #-}

-- | Like 'decodeStrict'' but returns an error message when decoding fails.
eitherDecodeStrict' :: (FromJSON a) => B.ByteString -> Either String a
eitherDecodeStrict' :: forall a. FromJSON a => ByteString -> Either FilePath a
eitherDecodeStrict' =
  Either (JSONPath, FilePath) a -> Either FilePath a
forall a. Either (JSONPath, FilePath) a -> Either FilePath a
eitherFormatError (Either (JSONPath, FilePath) a -> Either FilePath a)
-> (ByteString -> Either (JSONPath, FilePath) a)
-> ByteString
-> Either FilePath a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser Value
-> (Value -> IResult a)
-> ByteString
-> Either (JSONPath, FilePath) a
forall a.
Parser Value
-> (Value -> IResult a)
-> ByteString
-> Either (JSONPath, FilePath) a
eitherDecodeStrictWith Parser Value
jsonEOF' Value -> IResult a
forall a. FromJSON a => Value -> IResult a
ifromJSON
{-# INLINE eitherDecodeStrict' #-}

-- | Like 'decodeFileStrict'' but returns an error message when decoding fails.
eitherDecodeFileStrict' :: (FromJSON a) => FilePath -> IO (Either String a)
eitherDecodeFileStrict' :: forall a. FromJSON a => FilePath -> IO (Either FilePath a)
eitherDecodeFileStrict' =
  (ByteString -> Either FilePath a)
-> IO ByteString -> IO (Either FilePath a)
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> Either FilePath a
forall a. FromJSON a => ByteString -> Either FilePath a
eitherDecodeStrict' (IO ByteString -> IO (Either FilePath a))
-> (FilePath -> IO ByteString)
-> FilePath
-> IO (Either FilePath a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO ByteString
B.readFile
{-# INLINE eitherDecodeFileStrict' #-}

throwFormatError :: MonadThrow m => Either (JSONPath, String) a -> m a
throwFormatError :: forall (m :: * -> *) a.
MonadThrow m =>
Either (JSONPath, FilePath) a -> m a
throwFormatError = ((JSONPath, FilePath) -> m a)
-> (a -> m a) -> Either (JSONPath, FilePath) a -> m a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (AesonException -> m a
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (AesonException -> m a)
-> ((JSONPath, FilePath) -> AesonException)
-> (JSONPath, FilePath)
-> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> AesonException
AesonException (FilePath -> AesonException)
-> ((JSONPath, FilePath) -> FilePath)
-> (JSONPath, FilePath)
-> AesonException
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (JSONPath -> FilePath -> FilePath)
-> (JSONPath, FilePath) -> FilePath
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry JSONPath -> FilePath -> FilePath
formatError) a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return
{-# INLINE throwFormatError #-}

-- | Like 'decode' but throws an 'AesonException' when decoding fails.
--
-- >>> throwDecode "42" :: Maybe Int
-- Just 42
--
-- >>> throwDecode "42" :: IO Int
-- 42
--
-- >>> throwDecode "true" :: IO Int
-- ...Exception: AesonException...
--
-- @since 2.1.2.0
--
throwDecode :: forall a m. (FromJSON a, MonadThrow m) => L.ByteString -> m a
throwDecode :: forall a (m :: * -> *).
(FromJSON a, MonadThrow m) =>
ByteString -> m a
throwDecode = Either (JSONPath, FilePath) a -> m a
forall (m :: * -> *) a.
MonadThrow m =>
Either (JSONPath, FilePath) a -> m a
throwFormatError (Either (JSONPath, FilePath) a -> m a)
-> (ByteString -> Either (JSONPath, FilePath) a)
-> ByteString
-> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser Value
-> (Value -> IResult a)
-> ByteString
-> Either (JSONPath, FilePath) a
forall a.
Parser Value
-> (Value -> IResult a)
-> ByteString
-> Either (JSONPath, FilePath) a
eitherDecodeWith Parser Value
jsonEOF Value -> IResult a
forall a. FromJSON a => Value -> IResult a
ifromJSON
{-# INLINE throwDecode #-}

-- | Like 'decodeStrict' but throws an 'AesonException' when decoding fails.
--
-- @since 2.1.2.0
--
throwDecodeStrict :: forall a m. (FromJSON a, MonadThrow m) => B.ByteString -> m a
throwDecodeStrict :: forall a (m :: * -> *).
(FromJSON a, MonadThrow m) =>
ByteString -> m a
throwDecodeStrict =
  Either (JSONPath, FilePath) a -> m a
forall (m :: * -> *) a.
MonadThrow m =>
Either (JSONPath, FilePath) a -> m a
throwFormatError (Either (JSONPath, FilePath) a -> m a)
-> (ByteString -> Either (JSONPath, FilePath) a)
-> ByteString
-> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser Value
-> (Value -> IResult a)
-> ByteString
-> Either (JSONPath, FilePath) a
forall a.
Parser Value
-> (Value -> IResult a)
-> ByteString
-> Either (JSONPath, FilePath) a
eitherDecodeStrictWith Parser Value
jsonEOF Value -> IResult a
forall a. FromJSON a => Value -> IResult a
ifromJSON
{-# INLINE throwDecodeStrict #-}

-- | Like 'decode'' but throws an 'AesonException' when decoding fails.
--
-- @since 2.1.2.0
--
throwDecode' :: forall a m. (FromJSON a, MonadThrow m) => L.ByteString -> m a
throwDecode' :: forall a (m :: * -> *).
(FromJSON a, MonadThrow m) =>
ByteString -> m a
throwDecode' = Either (JSONPath, FilePath) a -> m a
forall (m :: * -> *) a.
MonadThrow m =>
Either (JSONPath, FilePath) a -> m a
throwFormatError (Either (JSONPath, FilePath) a -> m a)
-> (ByteString -> Either (JSONPath, FilePath) a)
-> ByteString
-> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser Value
-> (Value -> IResult a)
-> ByteString
-> Either (JSONPath, FilePath) a
forall a.
Parser Value
-> (Value -> IResult a)
-> ByteString
-> Either (JSONPath, FilePath) a
eitherDecodeWith Parser Value
jsonEOF' Value -> IResult a
forall a. FromJSON a => Value -> IResult a
ifromJSON
{-# INLINE throwDecode' #-}

-- | Like 'decodeStrict'' but throws an 'AesonException' when decoding fails.
--
-- @since 2.1.2.0
--
throwDecodeStrict' :: forall a m. (FromJSON a, MonadThrow m) => B.ByteString -> m a
throwDecodeStrict' :: forall a (m :: * -> *).
(FromJSON a, MonadThrow m) =>
ByteString -> m a
throwDecodeStrict' =
  Either (JSONPath, FilePath) a -> m a
forall (m :: * -> *) a.
MonadThrow m =>
Either (JSONPath, FilePath) a -> m a
throwFormatError (Either (JSONPath, FilePath) a -> m a)
-> (ByteString -> Either (JSONPath, FilePath) a)
-> ByteString
-> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser Value
-> (Value -> IResult a)
-> ByteString
-> Either (JSONPath, FilePath) a
forall a.
Parser Value
-> (Value -> IResult a)
-> ByteString
-> Either (JSONPath, FilePath) a
eitherDecodeStrictWith Parser Value
jsonEOF' Value -> IResult a
forall a. FromJSON a => Value -> IResult a
ifromJSON
{-# INLINE throwDecodeStrict' #-}

-- | Exception thrown by 'throwDecode' and variants.
--
-- @since 2.1.2.0
newtype AesonException = AesonException String
  deriving (Int -> AesonException -> FilePath -> FilePath
[AesonException] -> FilePath -> FilePath
AesonException -> FilePath
(Int -> AesonException -> FilePath -> FilePath)
-> (AesonException -> FilePath)
-> ([AesonException] -> FilePath -> FilePath)
-> Show AesonException
forall a.
(Int -> a -> FilePath -> FilePath)
-> (a -> FilePath) -> ([a] -> FilePath -> FilePath) -> Show a
$cshowsPrec :: Int -> AesonException -> FilePath -> FilePath
showsPrec :: Int -> AesonException -> FilePath -> FilePath
$cshow :: AesonException -> FilePath
show :: AesonException -> FilePath
$cshowList :: [AesonException] -> FilePath -> FilePath
showList :: [AesonException] -> FilePath -> FilePath
Show)

instance Exception AesonException where
    displayException :: AesonException -> FilePath
displayException (AesonException FilePath
str) = FilePath
"aeson: " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
str

-- $use
--
-- This section contains basic information on the different ways to
-- work with data using this library. These range from simple but
-- inflexible, to complex but flexible.
--
-- The most common way to use the library is to define a data type,
-- corresponding to some JSON data you want to work with, and then
-- write either a 'FromJSON' instance, a to 'ToJSON' instance, or both
-- for that type.
--
-- For example, given this JSON data:
--
-- > { "name": "Joe", "age": 12 }
--
-- we create a matching data type:
--
-- > {-# LANGUAGE DeriveGeneric #-}
-- >
-- > import GHC.Generics
-- >
-- > data Person = Person {
-- >       name :: Text
-- >     , age  :: Int
-- >     } deriving (Generic, Show)
--
-- The @LANGUAGE@ pragma and 'Generic' instance let us write empty
-- 'FromJSON' and 'ToJSON' instances for which the compiler will
-- generate sensible default implementations.
--
-- @
-- instance 'ToJSON' Person where
--     \-- No need to provide a 'toJSON' implementation.
--
--     \-- For efficiency, we write a simple 'toEncoding' implementation, as
--     \-- the default version uses 'toJSON'.
--     'toEncoding' = 'genericToEncoding' 'defaultOptions'
--
-- instance 'FromJSON' Person
--     \-- No need to provide a 'parseJSON' implementation.
-- @
--
-- We can now encode a value like so:
--
-- > >>> encode (Person {name = "Joe", age = 12})
-- > "{\"name\":\"Joe\",\"age\":12}"

-- $manual
--
-- When necessary, we can write 'ToJSON' and 'FromJSON' instances by
-- hand.  This is valuable when the JSON-on-the-wire and Haskell data
-- are different or otherwise need some more carefully managed
-- translation.  Let's revisit our JSON data:
--
-- > { "name": "Joe", "age": 12 }
--
-- We once again create a matching data type, without bothering to add
-- a 'Generic' instance this time:
--
-- > data Person = Person {
-- >       name :: Text
-- >     , age  :: Int
-- >     } deriving Show
--
-- To decode data, we need to define a 'FromJSON' instance:
--
-- > {-# LANGUAGE OverloadedStrings #-}
-- >
-- > instance FromJSON Person where
-- >     parseJSON = withObject "Person" $ \v -> Person
-- >         <$> v .: "name"
-- >         <*> v .: "age"
--
-- We can now parse the JSON data like so:
--
-- > >>> decode "{\"name\":\"Joe\",\"age\":12}" :: Maybe Person
-- > Just (Person {name = "Joe", age = 12})
--
-- To encode data, we need to define a 'ToJSON' instance. Let's begin
-- with an instance written entirely by hand.
--
-- @
-- instance ToJSON Person where
--     \-- this generates a 'Value'
--     'toJSON' (Person name age) =
--         'object' [\"name\" '.=' name, \"age\" '.=' age]
--
--     \-- this encodes directly to a bytestring Builder
--     'toEncoding' (Person name age) =
--         'pairs' (\"name\" '.=' 'name' '<>' \"age\" '.=' age)
-- @
--
-- We can now encode a value like so:
--
-- > >>> encode (Person {name = "Joe", age = 12})
-- > "{\"name\":\"Joe\",\"age\":12}"
--
-- There are predefined 'FromJSON' and 'ToJSON' instances for many
-- types. Here's an example using lists and 'Int's:
--
-- > >>> decode "[1,2,3]" :: Maybe [Int]
-- > Just [1,2,3]
--
-- And here's an example using the 'Data.Map.Map' type to get a map of
-- 'Int's.
--
-- > >>> decode "{\"foo\":1,\"bar\":2}" :: Maybe (Map String Int)
-- > Just (fromList [("bar",2),("foo",1)])

-- While the notes below focus on decoding, you can apply almost the
-- same techniques to /encoding/ data. (The main difference is that
-- encoding always succeeds, but decoding has to handle the
-- possibility of failure, where an input doesn't match our
-- expectations.)
--
-- See the documentation of 'FromJSON' and 'ToJSON' for some examples
-- of how you can automatically derive instances in many common
-- circumstances.

-- $ast
--
-- Sometimes you want to work with JSON data directly, without first
-- converting it to a custom data type. This can be useful if you want
-- to e.g. convert JSON data to YAML data, without knowing what the
-- contents of the original JSON data was. The 'Value' type, which is
-- an instance of 'FromJSON', is used to represent an arbitrary JSON
-- AST (abstract syntax tree). Example usage:
--
-- > >>> decode "{\"foo\": 123}" :: Maybe Value
-- > Just (Object (fromList [("foo",Number 123)]))
--
-- > >>> decode "{\"foo\": [\"abc\",\"def\"]}" :: Maybe Value
-- > Just (Object (fromList [("foo",Array (fromList [String "abc",String "def"]))]))
--
-- Once you have a 'Value' you can write functions to traverse it and
-- make arbitrary transformations.

-- $haskell
--
-- We can decode to any instance of 'FromJSON':
--
-- > λ> decode "[1,2,3]" :: Maybe [Int]
-- > Just [1,2,3]
--
-- Alternatively, there are instances for standard data types, so you
-- can use them directly. For example, use the 'Data.Map.Map' type to
-- get a map of 'Int's.
--
-- > λ> import Data.Map
-- > λ> decode "{\"foo\":1,\"bar\":2}" :: Maybe (Map String Int)
-- > Just (fromList [("bar",2),("foo",1)])

-- $mixed
--
-- The above approach with maps of course will not work for mixed-type
-- objects that don't follow a strict schema, but there are a couple
-- of approaches available for these.
--
-- The 'Object' type contains JSON objects:
--
-- > λ> decode "{\"name\":\"Dave\",\"age\":2}" :: Maybe Object
-- > Just (fromList [("name",String "Dave"),("age",Number 2)])
--
-- You can extract values from it with a parser using 'parse',
-- 'parseEither' or, in this example, 'parseMaybe':
--
-- > λ> do result <- decode "{\"name\":\"Dave\",\"age\":2}"
-- >       flip parseMaybe result $ \obj -> do
-- >         age <- obj .: "age"
-- >         name <- obj .: "name"
-- >         return (name ++ ": " ++ show (age*2))
-- >
-- > Just "Dave: 4"
--
-- Considering that any type that implements 'FromJSON' can be used
-- here, this is quite a powerful way to parse JSON. See the
-- documentation in 'FromJSON' for how to implement this class for
-- your own data types.
--
-- The downside is that you have to write the parser yourself; the
-- upside is that you have complete control over the way the JSON is
-- parsed.

-- $encoding_and_decoding
--
-- Decoding is a two-step process.
--
-- * When decoding a value, the process is reversed: the bytes are
--   converted to a 'Value', then the 'FromJSON' class is used to
--   convert to the desired type.
--
-- There are two ways to encode a value.
--
-- * Convert to a 'Value' using 'toJSON', then possibly further
--   encode.  This was the only method available in aeson 0.9 and
--   earlier.
--
-- * Directly encode (to what will become a 'L.ByteString') using
--   'toEncoding'.  This is much more efficient (about 3x faster, and
--   less memory intensive besides), but is only available in aeson
--   0.10 and newer.
--
-- For convenience, the 'encode' and 'decode' functions combine both
-- steps.

-- $encoding
--
-- In older versions of this library, encoding a Haskell value
-- involved converting to an intermediate 'Value', then encoding that.
--
-- A \"direct\" encoder converts straight from a source Haskell value
-- to a 'BL.ByteString' without constructing an intermediate 'Value'.
-- This approach is faster than 'toJSON', and allocates less memory.
-- The 'toEncoding' method makes it possible to implement direct
-- encoding with low memory overhead.
--
-- To complicate matters, the default implementation of 'toEncoding'
-- uses 'toJSON'.  Why?  The 'toEncoding' method was added to this
-- library much more recently than 'toJSON'.  Using 'toJSON' ensures
-- that packages written against older versions of this library will
-- compile and produce correct output, but they will not see any
-- speedup from direct encoding.
--
-- To write a minimal implementation of direct encoding, your type
-- must implement GHC's 'Generic' class, and your code should look
-- like this:
--
-- @
--     'toEncoding' = 'genericToEncoding' 'defaultOptions'
-- @
--
-- What if you have more elaborate encoding needs?  For example,
-- perhaps you need to change the names of object keys, omit parts of
-- a value.
--
-- To encode to a JSON \"object\", use the 'pairs' function.
--
-- @
--     'toEncoding' (Person name age) =
--         'pairs' (\"name\" '.=' 'name' '<>' \"age\" '.=' age)
-- @
--
-- Any container type that implements 'Foldable' can be encoded to a
-- JSON \"array\" using 'foldable'.
--
-- > > import Data.Sequence as Seq
-- > > encode (Seq.fromList [1,2,3])
-- > "[1,2,3]"

-- $time
--
-- This module contains instances of 'ToJSON' and 'FromJSON' for types from
-- the <https://hackage.haskell.org/package/time time> library.
--
-- Those instances encode time as JSON strings in
-- <https://en.wikipedia.org/wiki/ISO_8601 ISO 8601> formats, with the
-- following general form for 'Data.Time.Clock.UTCTime' and
-- 'Data.Time.LocalTime.ZonedTime', while other time types use subsets of those
-- fields:
--
-- > [+,-]YYYY-MM-DDThh:mm[:ss[.sss]]Z
--
-- where
--
-- - @[+,-]@ is an optional sign, @+@ or @-@.
-- - @YYYY@ is the year, which must have at least 4 digits to prevent Y2K problems.
--   Years from @0000@ to @0999@ must thus be zero-padded.
-- - @MM@ is a two-digit month.
-- - @DD@ is a two-digit day.
-- - @T@ is a literal @\'T\'@ character separating the date and the time of
--   day. It may be a space instead.
-- - @hh@ is a two-digit hour.
-- - @mm@ is a two-digit minute.
-- - @ss@ is a two-digit second.
-- - @sss@ is a decimal fraction of a second; it may have any nonzero number of digits.
-- - @Z@ is a time zone; it may be preceded by an optional space.
--
-- For more information, see <https://en.wikipedia.org/wiki/ISO_8601 ISO 8601>
-- <https://hackage.haskell.org/package/time time>,
-- and <https://hackage.haskell.org/package/attoparsec-iso8601 attoparsec-iso8601>
-- (where the relevant parsers are defined).