on master help sign in
Merge pull request #51 from hvr/issue-37

Add strict parsers variants of `json` and `value`

commitbe100f0868998569203ab62e01ae26da2731ed58 authorBryan O'Sullivan <bos@serpentine.com> dateWed 30 Nov 2011, 09:56 (15 years ago) parent1fa8f4dcd3a788
1 file changed+51
Data/Aeson/Parser.hs+51
Data/Aeson/Parser.hs+51
@@ -14,7 +14,9 @@
1414module Data.Aeson.Parser
1515 (
1616 json
17+ , json'
1718 , value
19+ , value'
1820 , jstring
1921 ) where
2022
@@ -47,6 +49,19 @@ json = do
4749 then object_
4850 else array_
4951
52+-- | Parse a top-level JSON value. This must be either an object or
53+-- an array.
54+--
55+-- This is a strict parser version of 'json' which avoids
56+-- building up thunks during parsing. Prefer this version if most of
57+-- the JSON data needs to be accessed.
58+json' :: Parser Value
59+json' = do
60+ c <- skipSpace *> satisfy (`B8.elem` "{[")
61+ if c == '{'
62+ then object_'
63+ else array_'
64+
5065object_ :: Parser Value
5166object_ = {-# SCC "object_" #-} do
5267 skipSpace
@@ -57,12 +72,28 @@ object_ = {-# SCC "object_" #-} do
5772 vals <- ((pair <* skipSpace) `sepBy` (char ',' *> skipSpace)) <* char '}'
5873 return . Object $ H.fromList vals
5974
75+object_' :: Parser Value
76+object_' = {-# SCC "object_'" #-} do
77+ skipSpace
78+ let pair = do
79+ a <- jstring <* skipSpace
80+ b <- char ':' *> skipSpace *> value'
81+ return (a,b)
82+ vals <- ((pair <* skipSpace) `sepBy` (char ',' *> skipSpace)) <* char '}'
83+ return $! Object $ H.fromList vals
84+
6085array_ :: Parser Value
6186array_ = {-# SCC "array_" #-} do
6287 skipSpace
6388 vals <- ((value <* skipSpace) `sepBy` (char ',' *> skipSpace)) <* char ']'
6489 return . Array $ Vector.fromList vals
6590
91+array_' :: Parser Value
92+array_' = {-# SCC "array_'" #-} do
93+ skipSpace
94+ vals <- ((value' <* skipSpace) `sepBy` (char ',' *> skipSpace)) <* char ']'
95+ return $! Array $ Vector.fromList vals
96+
6697-- | Parse any JSON value. Use 'json' in preference to this function
6798-- if you are parsing data from an untrusted source.
6899value :: Parser Value
@@ -79,6 +110,26 @@ value = most <|> (Number <$> number)
79110 'n' -> string "ull" *> pure Null
80111 _ -> error "attoparsec panic! the impossible happened!"
81112
113+-- | Strict version of 'value'. See also 'json''.
114+value' :: Parser Value
115+value' = most <|> num
116+ where
117+ num = do
118+ n <- number
119+ return $! Number n
120+ most = do
121+ c <- satisfy (`B8.elem` "{[\"ftn")
122+ case c of
123+ '{' -> object_'
124+ '[' -> array_'
125+ '"' -> do
126+ s <- jstring_
127+ return $! String s
128+ 'f' -> string "alse" *> pure (Bool False)
129+ 't' -> string "rue" *> pure (Bool True)
130+ 'n' -> string "ull" *> pure Null
131+ _ -> error "attoparsec panic! the impossible happened!"
132+
82133doubleQuote, backslash :: Word8
83134doubleQuote = 34
84135backslash = 92