Skip to content

Commit 105fe14

Browse files
authored
Merge pull request #988 from haskell/throwDecode
Add throwDecode and variants
2 parents 0dbe06b + 76246ad commit 105fe14

File tree

7 files changed

+95
-6
lines changed

7 files changed

+95
-6
lines changed

.github/workflows/haskell-ci.yml

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ jobs:
170170
run: |
171171
$CABAL v2-update -v
172172
- name: cache (tools)
173-
uses: actions/cache@v2
173+
uses: actions/cache@v3
174174
with:
175175
key: ${{ runner.os }}-${{ matrix.compiler }}-tools-cd9045c2
176176
path: ~/.haskell-ci-tools
@@ -183,8 +183,17 @@ jobs:
183183
rm -f cabal-plan.xz
184184
chmod a+x $HOME/.cabal/bin/cabal-plan
185185
cabal-plan --version
186+
- name: install cabal-docspec
187+
run: |
188+
mkdir -p $HOME/.cabal/bin
189+
curl -sL https://github.com/phadej/cabal-extras/releases/download/cabal-docspec-0.0.0.20211114/cabal-docspec-0.0.0.20211114.xz > cabal-docspec.xz
190+
echo 'e224700d9e8c9ec7ec6bc3f542ba433cd9925a5d356676c62a9bd1f2c8be8f8a cabal-docspec.xz' | sha256sum -c -
191+
xz -d < cabal-docspec.xz > $HOME/.cabal/bin/cabal-docspec
192+
rm -f cabal-docspec.xz
193+
chmod a+x $HOME/.cabal/bin/cabal-docspec
194+
cabal-docspec --version
186195
- name: checkout
187-
uses: actions/checkout@v2
196+
uses: actions/checkout@v3
188197
with:
189198
path: source
190199
- name: initial cabal.project for sdist
@@ -232,7 +241,7 @@ jobs:
232241
$CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dry-run all
233242
cabal-plan
234243
- name: cache
235-
uses: actions/cache@v2
244+
uses: actions/cache@v3
236245
with:
237246
key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }}
238247
path: ~/.cabal/store
@@ -250,6 +259,10 @@ jobs:
250259
- name: tests
251260
run: |
252261
$CABAL v2-test $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --test-show-details=direct
262+
- name: docspec
263+
run: |
264+
$CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH all
265+
cabal-docspec $ARG_COMPILER
253266
- name: haddock
254267
run: |
255268
if [ $((HCNUMVER >= 80600)) -ne 0 ] ; then $CABAL v2-haddock --haddock-all $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH all ; fi

.github/workflows/z-bench.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ jobs:
174174
chmod a+x $HOME/.cabal/bin/cabal-plan
175175
cabal-plan --version
176176
- name: checkout
177-
uses: actions/checkout@v2
177+
uses: actions/checkout@v3
178178
with:
179179
path: source
180180
- name: initial cabal.project for sdist
@@ -210,7 +210,7 @@ jobs:
210210
$CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dry-run all
211211
cabal-plan
212212
- name: cache
213-
uses: actions/cache@v2
213+
uses: actions/cache@v3
214214
with:
215215
key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }}
216216
path: ~/.cabal/store

aeson.cabal

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: aeson
2-
version: 2.1.1.0
2+
version: 2.1.2.0
33
license: BSD3
44
license-file: LICENSE
55
category: Text, Web, JSON
@@ -102,6 +102,7 @@ library
102102
, ghc-prim >=0.5.0.0 && <0.10
103103
, template-haskell >=2.11.0.0 && <2.20
104104
, text >=1.2.3.0 && <1.3 || >=2.0 && <2.1
105+
, exceptions >=0.10.4 && <0.11
105106
, time >=1.6.0.1 && <1.13
106107

107108
-- Compat

benchmarks/aeson-benchmarks.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ library
3131
, data-fix
3232
, deepseq
3333
, dlist
34+
, exceptions
3435
, generically
3536
, ghc-prim
3637
, hashable

cabal.haskell-ci

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
branches: master
22
cabal-check: False
3+
docspec: True
34

45
-- GADT docs
56
haddock: >=8.6

changelog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ For the latest version of this document, please see [https://github.com/haskell/
22

33
### 2.1.2.0
44

5+
* Add `throwDecode :: (MonadThrow m, FromJSON a) => ByteString -> m a`
6+
and variants.
7+
8+
### 2.1.2.0
9+
510
* Support deriving for empty datatypes (such as `Void` and `V1`)
611
in `FromJSON` and `ToJSON`.
712
* Add `To/FromJSONKey Void` instances

src/Data/Aeson.hs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
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

155162
import Prelude.Compat
156163

164+
import Control.Exception (Exception (..))
165+
import Control.Monad.Catch (MonadThrow (..))
157166
import Data.Aeson.Types.FromJSON (ifromJSON, parseIndexedJSON)
158167
import Data.Aeson.Encoding (encodingToLazyByteString)
159168
import Data.Aeson.Parser.Internal (decodeWith, decodeStrictWith, eitherDecodeWith, eitherDecodeStrictWith, jsonEOF, json, jsonEOF', json')
@@ -162,6 +171,9 @@ import Data.Aeson.Types.Internal (formatError)
162171
import qualified Data.ByteString as B
163172
import 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

Comments
 (0)