on master help sign in
Allow decoding of strict bytestrings (gh-99)
commit371ebaed7f855457d2653dba921876f2d6d8dcfc authorBryan O'Sullivan <bos@serpentine.com> dateWed 4 Sep 2013, 11:41 (13 years ago) parent04520e1
2 files changed+70−3
Data/Aeson.hs+45−2 Data/Aeson/Parser/Internal.hs+25−1
Data/Aeson.hs+45−2
@@ -40,6 +40,11 @@ module Data.Aeson
4040 , eitherDecode
4141 , eitherDecode'
4242 , encode
43+ -- ** Variants for strict bytestrings
44+ , decodeStrict
45+ , decodeStrict'
46+ , eitherDecodeStrict
47+ , eitherDecodeStrict'
4348 -- * Core JSON types
4449 , Value(..)
4550 , Array
@@ -76,9 +81,11 @@ module Data.Aeson
7681 ) where
7782
7883import Data.Aeson.Encode (encode)
79−import Data.Aeson.Parser.Internal (decodeWith, eitherDecodeWith, jsonEOF, json,
80− jsonEOF', json')
84+import Data.Aeson.Parser.Internal (decodeWith, decodeStrictWith,
85+ eitherDecodeWith, eitherDecodeStrictWith,
86+ jsonEOF, json, jsonEOF', json')
8187import Data.Aeson.Types
88+import qualified Data.ByteString as B
8289import qualified Data.ByteString.Lazy as L
8390
8491-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
@@ -97,6 +104,19 @@ decode :: (FromJSON a) => L.ByteString -> Maybe a
97104decode = decodeWith jsonEOF fromJSON
98105{-# INLINE decode #-}
99106
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+
100120-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
101121-- If this fails due to incomplete or invalid input, 'Nothing' is
102122-- returned.
@@ -113,16 +133,39 @@ decode' :: (FromJSON a) => L.ByteString -> Maybe a
113133decode' = decodeWith jsonEOF' fromJSON
114134{-# INLINE decode' #-}
115135
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+
116149-- | Like 'decode' but returns an error message when decoding fails.
117150eitherDecode :: (FromJSON a) => L.ByteString -> Either String a
118151eitherDecode = eitherDecodeWith jsonEOF fromJSON
119152{-# INLINE eitherDecode #-}
120153
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+
121159-- | Like 'decode'' but returns an error message when decoding fails.
122160eitherDecode' :: (FromJSON a) => L.ByteString -> Either String a
123161eitherDecode' = eitherDecodeWith jsonEOF' fromJSON
124162{-# INLINE eitherDecode' #-}
125163
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+
126169-- $use
127170--
128171-- 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
2323 , value'
2424 -- * Helpers
2525 , decodeWith
26+ , decodeStrictWith
2627 , eitherDecodeWith
28+ , eitherDecodeStrictWith
2729 ) where
2830
2931import Blaze.ByteString.Builder (fromByteString, toByteString)
@@ -244,7 +246,18 @@ decodeWith p to s =
244246 _ -> Nothing
245247{-# INLINE decodeWith #-}
246248
247−eitherDecodeWith :: Parser Value -> (Value -> Result a) -> L.ByteString -> Either String a
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+
259+eitherDecodeWith :: Parser Value -> (Value -> Result a) -> L.ByteString
260+ -> Either String a
248261eitherDecodeWith p to s =
249262 case L.parse p s of
250263 L.Done _ v -> case to v of
@@ -253,6 +266,17 @@ eitherDecodeWith p to s =
253266 L.Fail _ _ msg -> Left msg
254267{-# INLINE eitherDecodeWith #-}
255268
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+
256280-- $lazy
257281--
258282-- The 'json' and 'value' parsers decouple identification from