From 2f10f5fac3c676daf34179e93ff5fdc26c98b72c Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Wed, 11 Sep 2019 00:37:05 +0200 Subject: [PATCH] fixes #12152 --- changelog.md | 4 ++++ lib/pure/json.nim | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/changelog.md b/changelog.md index 5735dd033cdf..7a14c6c2833a 100644 --- a/changelog.md +++ b/changelog.md @@ -47,6 +47,10 @@ type - Added `system.getOsFileHandle` which is usually more useful than `system.getFileHandle`. This distinction is only meaningful on Windows. +- Added a `json.parseJsonFragments` iterator that can be used to speedup + JSON processing substantially when there are JSON fragments separated + by whitespace. + ## Library changes diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 23b23b4a4649..668e672a110c 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -841,10 +841,27 @@ proc parseJson(p: var JsonParser): JsonNode = raiseParseErr(p, "{") when not defined(js): + iterator parseJsonFragments*(s: Stream, filename: string = ""): JsonNode = + ## Parses from a stream `s` into `JsonNodes`. `filename` is only needed + ## for nice error messages. + ## The JSON fragments are separated by whitespace. This can be substantially + ## faster than the comparable loop + ## ``for x in splitWhitespace(s): yield parseJson(x)``. + ## This closes the stream `s` after it's done. + var p: JsonParser + p.open(s, filename) + try: + discard getTok(p) # read first token + while p.tok != tkEof: + yield p.parseJson() + finally: + p.close() + proc parseJson*(s: Stream, filename: string = ""): JsonNode = ## Parses from a stream `s` into a `JsonNode`. `filename` is only needed ## for nice error messages. ## If `s` contains extra data, it will raise `JsonParsingError`. + ## This closes the stream `s` after it's done. var p: JsonParser p.open(s, filename) try: @@ -1778,3 +1795,10 @@ when isMainModule: ) doAssert(obj == to(%obj, type(obj))) + + const fragments = """[1,2,3] {"hi":3} 12 [] """ + var res = "" + for x in parseJsonFragments(newStringStream(fragments)): + res.add($x) + res.add " " + doAssert res == fragments