11{-# LANGUAGE NoImplicitPrelude #-}
2+ {-# LANGUAGE ScopedTypeVariables #-}
23-- |
34-- Module: Data.Aeson
45-- Copyright: (c) 2011-2016 Bryan O'Sullivan
@@ -55,6 +56,12 @@ module Data.Aeson
5556 , eitherDecodeFileStrict
5657 , eitherDecodeStrict'
5758 , eitherDecodeFileStrict'
59+ -- ** Exception throwing variants
60+ , AesonException (.. )
61+ , throwDecode
62+ , throwDecodeStrict
63+ , throwDecode'
64+ , throwDecodeStrict'
5865 -- * Core JSON types
5966 , Value (.. )
6067 , Encoding
@@ -154,6 +161,8 @@ module Data.Aeson
154161
155162import Prelude.Compat
156163
164+ import Control.Exception (Exception (.. ))
165+ import Control.Monad.Catch (MonadThrow (.. ))
157166import Data.Aeson.Types.FromJSON (ifromJSON , parseIndexedJSON )
158167import Data.Aeson.Encoding (encodingToLazyByteString )
159168import Data.Aeson.Parser.Internal (decodeWith , decodeStrictWith , eitherDecodeWith , eitherDecodeStrictWith , jsonEOF , json , jsonEOF' , json' )
@@ -162,6 +171,9 @@ import Data.Aeson.Types.Internal (formatError)
162171import qualified Data.ByteString as B
163172import qualified Data.ByteString.Lazy as L
164173
174+ -- $setup
175+ -- >>> :set -XOverloadedStrings
176+
165177-- | Efficiently serialize a JSON value as a lazy 'L.ByteString'.
166178--
167179-- This is implemented in terms of the 'ToJSON' class's 'toEncoding' method.
@@ -286,6 +298,62 @@ eitherDecodeFileStrict' =
286298 fmap eitherDecodeStrict' . B. readFile
287299{-# INLINE eitherDecodeFileStrict' #-}
288300
301+ throwFormatError :: MonadThrow m => Either (JSONPath , String ) a -> m a
302+ throwFormatError = either (throwM . AesonException . uncurry formatError) return
303+ {-# INLINE throwFormatError #-}
304+
305+ -- | Like 'decode' but throws an 'AesonException' when decoding fails.
306+ --
307+ -- >>> throwDecode "42" :: Maybe Int
308+ -- Just 42
309+ --
310+ -- >>> throwDecode "42" :: IO Int
311+ -- 42
312+ --
313+ -- >>> throwDecode "true" :: IO Int
314+ -- ...Exception: AesonException...
315+ --
316+ -- @since 2.1.2.0
317+ --
318+ throwDecode :: forall a m . (FromJSON a , MonadThrow m ) => L. ByteString -> m a
319+ throwDecode = throwFormatError . eitherDecodeWith jsonEOF ifromJSON
320+ {-# INLINE throwDecode #-}
321+
322+ -- | Like 'decodeStrict' but throws an 'AesonException' when decoding fails.
323+ --
324+ -- @since 2.1.2.0
325+ --
326+ throwDecodeStrict :: forall a m . (FromJSON a , MonadThrow m ) => B. ByteString -> m a
327+ throwDecodeStrict =
328+ throwFormatError . eitherDecodeStrictWith jsonEOF ifromJSON
329+ {-# INLINE throwDecodeStrict #-}
330+
331+ -- | Like 'decode'' but throws an 'AesonException' when decoding fails.
332+ --
333+ -- @since 2.1.2.0
334+ --
335+ throwDecode' :: forall a m . (FromJSON a , MonadThrow m ) => L. ByteString -> m a
336+ throwDecode' = throwFormatError . eitherDecodeWith jsonEOF' ifromJSON
337+ {-# INLINE throwDecode' #-}
338+
339+ -- | Like 'decodeStrict'' but throws an 'AesonException' when decoding fails.
340+ --
341+ -- @since 2.1.2.0
342+ --
343+ throwDecodeStrict' :: forall a m . (FromJSON a , MonadThrow m ) => B. ByteString -> m a
344+ throwDecodeStrict' =
345+ throwFormatError . eitherDecodeStrictWith jsonEOF' ifromJSON
346+ {-# INLINE throwDecodeStrict' #-}
347+
348+ -- | Exception thrown by 'throwDecode' and variants.
349+ --
350+ -- @since 2.1.2.0
351+ newtype AesonException = AesonException String
352+ deriving (Show )
353+
354+ instance Exception AesonException where
355+ displayException (AesonException str) = " aeson: " ++ str
356+
289357-- $use
290358--
291359-- This section contains basic information on the different ways to
0 commit comments