on master help sign in
Allow decoding of strict bytestrings (gh-99)
371ebaeBryan O'Sullivan
Data/Aeson.hs+45−2
@@ -40,6 +40,11 @@ module Data.Aeson
40 , eitherDecode
40 , eitherDecode
41 , eitherDecode'
41 , eitherDecode'
42 , encode
42 , encode
43+ -- ** Variants for strict bytestrings
44+ , decodeStrict
45+ , decodeStrict'
46+ , eitherDecodeStrict
47+ , eitherDecodeStrict'
43 -- * Core JSON types
48 -- * Core JSON types
44 , Value(..)
49 , Value(..)
45 , Array
50 , Array
@@ -76,9 +81,11 @@ module Data.Aeson
76 ) where
81 ) where
77
82
78import Data.Aeson.Encode (encode)
83import Data.Aeson.Encode (encode)
79−import Data.Aeson.Parser.Internal (decodeWith, eitherDecodeWith, jsonEOF, json,
84+import Data.Aeson.Parser.Internal (decodeWith, decodeStrictWith,
85+ eitherDecodeWith, eitherDecodeStrictWith,
80− jsonEOF', json')
86+ jsonEOF, json, jsonEOF', json')
81import Data.Aeson.Types
87import Data.Aeson.Types
88+import qualified Data.ByteString as B
82import qualified Data.ByteString.Lazy as L
89import qualified Data.ByteString.Lazy as L
83
90
84-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
91-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
@@ -97,6 +104,19 @@ decode :: (FromJSON a) => L.ByteString -> Maybe a
97decode = decodeWith jsonEOF fromJSON
104decode = decodeWith jsonEOF fromJSON
98{-# INLINE decode #-}
105{-# INLINE decode #-}
99
106
107+-- | Efficiently deserialize a JSON value from a strict 'B.ByteString'.
108+-- If this fails due to incomplete or invalid input, 'Nothing' is
109+-- returned.
110+--
111+-- The input must consist solely of a JSON document, with no trailing
112+-- data except for whitespace.
113+--
114+-- This function parses immediately, but defers conversion. See
115+-- 'json' for details.
116+decodeStrict :: (FromJSON a) => B.ByteString -> Maybe a
117+decodeStrict = decodeStrictWith jsonEOF fromJSON
118+{-# INLINE decodeStrict #-}
119+
100-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
120-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
101-- If this fails due to incomplete or invalid input, 'Nothing' is
121-- If this fails due to incomplete or invalid input, 'Nothing' is
102-- returned.
122-- returned.
@@ -113,16 +133,39 @@ decode' :: (FromJSON a) => L.ByteString -> Maybe a
113decode' = decodeWith jsonEOF' fromJSON
133decode' = decodeWith jsonEOF' fromJSON
114{-# INLINE decode' #-}
134{-# INLINE decode' #-}
115
135
136+-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
137+-- If this fails due to incomplete or invalid input, 'Nothing' is
138+-- returned.
139+--
140+-- The input must consist solely of a JSON document, with no trailing
141+-- data except for whitespace.
142+--
143+-- This function parses and performs conversion immediately. See
144+-- 'json'' for details.
145+decodeStrict' :: (FromJSON a) => B.ByteString -> Maybe a
146+decodeStrict' = decodeStrictWith jsonEOF' fromJSON
147+{-# INLINE decodeStrict' #-}
148+
116-- | Like 'decode' but returns an error message when decoding fails.
149-- | Like 'decode' but returns an error message when decoding fails.
117eitherDecode :: (FromJSON a) => L.ByteString -> Either String a
150eitherDecode :: (FromJSON a) => L.ByteString -> Either String a
118eitherDecode = eitherDecodeWith jsonEOF fromJSON
151eitherDecode = eitherDecodeWith jsonEOF fromJSON
119{-# INLINE eitherDecode #-}
152{-# INLINE eitherDecode #-}
120
153
154+-- | Like 'decodeStrict' but returns an error message when decoding fails.
155+eitherDecodeStrict :: (FromJSON a) => B.ByteString -> Either String a
156+eitherDecodeStrict = eitherDecodeStrictWith jsonEOF fromJSON
157+{-# INLINE eitherDecodeStrict #-}
158+
121-- | Like 'decode'' but returns an error message when decoding fails.
159-- | Like 'decode'' but returns an error message when decoding fails.
122eitherDecode' :: (FromJSON a) => L.ByteString -> Either String a
160eitherDecode' :: (FromJSON a) => L.ByteString -> Either String a
123eitherDecode' = eitherDecodeWith jsonEOF' fromJSON
161eitherDecode' = eitherDecodeWith jsonEOF' fromJSON
124{-# INLINE eitherDecode' #-}
162{-# INLINE eitherDecode' #-}
125
163
164+-- | Like 'decodeStrict'' but returns an error message when decoding fails.
165+eitherDecodeStrict' :: (FromJSON a) => B.ByteString -> Either String a
166+eitherDecodeStrict' = eitherDecodeStrictWith jsonEOF' fromJSON
167+{-# INLINE eitherDecodeStrict' #-}
168+
126-- $use
169-- $use
127--
170--
128-- This section contains basic information on the different ways to
171-- This section contains basic information on the different ways to
Data/Aeson/Parser/Internal.hs+25−1
@@ -23,7 +23,9 @@ module Data.Aeson.Parser.Internal
23 , value'
23 , value'
24 -- * Helpers
24 -- * Helpers
25 , decodeWith
25 , decodeWith
26+ , decodeStrictWith
26 , eitherDecodeWith
27 , eitherDecodeWith
28+ , eitherDecodeStrictWith
27 ) where
29 ) where
28
30
29import Blaze.ByteString.Builder (fromByteString, toByteString)
31import Blaze.ByteString.Builder (fromByteString, toByteString)
@@ -244,7 +246,18 @@ decodeWith p to s =
244 _ -> Nothing
246 _ -> Nothing
245{-# INLINE decodeWith #-}
247{-# INLINE decodeWith #-}
246
248
249+decodeStrictWith :: Parser Value -> (Value -> Result a) -> B.ByteString
250+ -> Maybe a
251+decodeStrictWith p to s =
252+ case A.parse p s of
253+ A.Done _ v -> case to v of
254+ Success a -> Just a
255+ _ -> Nothing
256+ _ -> Nothing
257+{-# INLINE decodeStrictWith #-}
258+
247−eitherDecodeWith :: Parser Value -> (Value -> Result a) -> L.ByteString -> Either String a
259+eitherDecodeWith :: Parser Value -> (Value -> Result a) -> L.ByteString
260+ -> Either String a
248eitherDecodeWith p to s =
261eitherDecodeWith p to s =
249 case L.parse p s of
262 case L.parse p s of
250 L.Done _ v -> case to v of
263 L.Done _ v -> case to v of
@@ -253,6 +266,17 @@ eitherDecodeWith p to s =
253 L.Fail _ _ msg -> Left msg
266 L.Fail _ _ msg -> Left msg
254{-# INLINE eitherDecodeWith #-}
267{-# INLINE eitherDecodeWith #-}
255
268
269+eitherDecodeStrictWith :: Parser Value -> (Value -> Result a) -> B.ByteString
270+ -> Either String a
271+eitherDecodeStrictWith p to s =
272+ case A.parse p s of
273+ A.Done _ v -> case to v of
274+ Success a -> Right a
275+ Error msg -> Left msg
276+ A.Fail _ _ msg -> Left msg
277+ A.Partial _ -> Left "incomplete input"
278+{-# INLINE eitherDecodeStrictWith #-}
279+
256-- $lazy
280-- $lazy
257--
281--
258-- The 'json' and 'value' parsers decouple identification from
282-- The 'json' and 'value' parsers decouple identification from