Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Release Notes

## 8.1.4 - Mar 30 2026

- Performance: `JsonValue.Parse` now copies unescaped string runs in bulk instead of appending character-by-character, reducing `StringBuilder.Append` calls for strings with few or no escape sequences

## 8.1.3 - Mar 23 2026

- Fix JSON `/* ... */` comment parser: `*` or `/` characters inside the comment body no longer cause premature termination and parse failure
Expand Down
14 changes: 13 additions & 1 deletion src/FSharp.Data.Json.Core/JsonValue.fs
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,18 @@ type private JsonParser(jsonText: string) =
ensure (i < s.Length && s.[i] = '"')
i <- i + 1

// Track start of current unescaped run; flush as a bulk chunk when an escape or end is hit.
// This avoids per-character StringBuilder.Append calls for strings with few/no escapes,
// which is the common case in real-world JSON.
let mutable chunkStart = i

let inline flushChunk upTo =
if upTo > chunkStart then
buf.Append(s, chunkStart, upTo - chunkStart) |> ignore

while i < s.Length && s.[i] <> '"' do
if s.[i] = '\\' then
flushChunk i
ensure (i + 1 < s.Length)

match s.[i + 1] with
Expand Down Expand Up @@ -371,10 +381,12 @@ type private JsonParser(jsonText: string) =
| _ -> throw ()

i <- i + 2 // skip past \ and next char
chunkStart <- i
else
buf.Append(s.[i]) |> ignore
i <- i + 1

// Flush any remaining unescaped characters
flushChunk i
ensure (i < s.Length && s.[i] = '"')
i <- i + 1
let str = buf.ToString()
Expand Down
Loading