summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md4
-rw-r--r--lib/pure/json.nim25
2 files changed, 29 insertions, 0 deletions
diff --git a/changelog.md b/changelog.md
index 5735dd033..7a14c6c28 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 23b23b4a4..597c0891f 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,11 @@ when isMainModule:
     )
 
     doAssert(obj == to(%obj, type(obj)))
+
+    when not defined(js):
+      const fragments = """[1,2,3] {"hi":3} 12 [] """
+      var res = ""
+      for x in parseJsonFragments(newStringStream(fragments)):
+        res.add($x)
+        res.add " "
+      doAssert res == fragments