json-stream 0.4.2.1 → 0.4.2.2
raw patch · 3 files changed
+39/−19 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- Data/JsonStream/Parser.hs +13/−5
- README.md +25/−13
- json-stream.cabal +1/−1
Data/JsonStream/Parser.hs view
@@ -232,14 +232,13 @@ process _ _ _ = Failed "Unexpected error in parallel processing <|>" some = filterI (not . null) . many- many f = Parser $ \ntok -> loop [] (callParse f ntok)+ many f = Parser $ \ntok -> loop id (callParse f ntok) where- loop acc (Done ctx ntp) = Yield (reverse acc) (Done ctx ntp)+ loop acc (Done ctx ntp) = Yield (acc []) (Done ctx ntp) loop acc (MoreData (Parser np, ntok)) = MoreData (Parser (loop acc . np), ntok)- loop acc (Yield v np) = loop (v:acc) np+ loop acc (Yield v np) = loop (\nxt -> acc (v : nxt)) np loop _ (Failed err) = Failed err - array' :: (Int -> Parser a) -> Parser a array' valparse = Parser $ \tp -> case tp of@@ -375,8 +374,17 @@ JInteger val -> Yield (AE.Number $ fromIntegral val) (Done "" ntok) StringContent _ -> callParse (AE.String <$> longString Nothing) tok ArrayBegin -> AE.Array . Vec.fromList <$> callParse (many (arrayOf aeValue)) tok- ObjectBegin -> AE.Object . HMap.fromList <$> callParse (many (objectItems aeValue)) tok+ ObjectBegin -> AE.Object . HMap.fromList <$> callParse (manyReverse (objectItems aeValue)) tok _ -> Failed ("aeValue - unexpected token: " ++ show el)++-- | Optimized function for aeson objects - evades reversing the objects+manyReverse :: Parser a -> Parser [a]+manyReverse f = Parser $ \ntok -> loop [] (callParse f ntok)+ where+ loop acc (Done ctx ntp) = Yield acc (Done ctx ntp)+ loop acc (MoreData (Parser np, ntok)) = MoreData (Parser (loop acc . np), ntok)+ loop acc (Yield v np) = loop (v : acc) np+ loop _ (Failed err) = Failed err -- | Convert a strict aeson value (no object/array) to a value. -- Non-matching type is ignored and not parsed (unlike 'value')
README.md view
@@ -2,11 +2,21 @@ [](https://travis-ci.org/ondrap/json-stream) [](https://hackage.haskell.org/package/json-stream) +# When to use this library++- use [aeson](https://hackage.haskell.org/package/aeson) if you can; compile aeson with `cffi` flag if you need better performance+- use `json-stream` if you+ - need streaming+ - need every bit of performance (do profile; aeson is quite fast these days)+ - do not care that parsing may not fail on malformed JSON data+ - do not need advanced error reporting; json-stream tends to skip data that+ doesn't fit parsing rules (this might be implemented better in the future)++# Intro+ Most haskellers use the excellent [aeson](https://hackage.haskell.org/package/aeson) library to decode and encode JSON structures. Unfortunately, although very fast, this parser-must read the whole structure into memory. At a first sight it seemed that creating-an incremental JSON parser would be very hard thing to do; it turned out to be-remarkable easy. Just wondering, why nobody came with this earlier...+must read the whole structure into memory. Json-stream allows incremental parsing. > Parsing performance is generally better than aeson, sometimes significantly better. > Json-stream uses a small and fast C lexer to parse the JSON into tokens. This results@@ -67,22 +77,24 @@ ``` ## Performance -Json-stream is fast. The crude lexing is done by a C-optimized code in batches, the-lexed pieces are then parsed using the user-specified parser. Compared to aeson, parsing-can be easily twice as fast, especially on larger structures.-Json-stream is in streaming mode much friendlier to the GC,-which makes the performance difference even bigger; however even when json-stream is used-as an aeson replacement (`value` parser), there can be a performance gain (running aeson benchmarks-has shown that json-stream is generally about twice as fast).+The crude lexing is done by a C-optimized code in batches, the+lexed pieces are then parsed using the user-specified parser. Json-stream+is generally slightly faster than aeson. It is significantly faster+in the following scenarios: +- parsing numbers+- parsing strings when aeson is not compiled with `cffi` flag+ (the `cffi` flag of aeson enables fast text decoding borrowed from json-stream)+- parsing only subset of big JSON structures++Json-stream is in streaming mode is also much friendlier to the GC.+ Using json-stream parser instead of aeson `value` evades the need to build the structure using aeson `Value` and then converting it to the user-requested structure. Instead the structure is built on the fly directly during the parsing phase. Json-stream can optimize certain scenarios. If not all data from the input stream is-required, it is skipped by the parsers. Using `integer` parser-with bounded integer types (not `Integer`) avoids converting all numbers to-`Scientific` type.+required, it is skipped by the parsers. ## Constant space parsing
json-stream.cabal view
@@ -1,5 +1,5 @@ name: json-stream-version: 0.4.2.1+version: 0.4.2.2 synopsis: Incremental applicative JSON parser description: Easy to use JSON parser fully supporting incremental parsing. Parsing grammar in applicative form.