Skip to content
Closed
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
23 changes: 19 additions & 4 deletions src/FSharp.Data.Json.Core/JsonDocument.fs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,22 @@ type JsonDocument =
use reader = reader
let text = reader.ReadToEnd()

match JsonValue.ParseMultiple(text) |> Seq.toArray with
| [| JsonValue.Array array |] -> array
| array -> array
|> Array.mapi (fun i value -> JsonDocument.Create(value, "[" + (string i) + "]"))
// Optimization: Process parsed values more efficiently to reduce allocations
let parsedSequence = JsonValue.ParseMultiple(text)

// Convert to array only once and handle the special case efficiently
let parsedArray = parsedSequence |> Seq.toArray

let valuesArray =
match parsedArray with
| [| JsonValue.Array array |] -> array
| array -> array

// Optimization: Pre-allocate result array instead of using Array.mapi
// This avoids creating intermediate mapping functions and reduces allocations
let resultArray = Array.zeroCreate<IJsonDocument> valuesArray.Length

for i = 0 to valuesArray.Length - 1 do
resultArray.[i] <- JsonDocument.Create(valuesArray.[i], "[" + (string i) + "]")

resultArray
33 changes: 24 additions & 9 deletions src/FSharp.Data.Json.Core/JsonRuntime.fs
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,19 @@ type JsonRuntime =
static member ConvertArray<'T>(doc: IJsonDocument, mapping: Func<IJsonDocument, 'T>) =
match doc.JsonValue with
| JsonValue.Array elements ->
elements
|> Array.filter (function
| JsonValue.Null -> false
| JsonValue.String s when s |> TextConversions.AsString |> Option.isNone -> false
| _ -> true)
|> Array.mapi (fun i value -> doc.CreateNew(value, "[" + (string i) + "]") |> mapping.Invoke)
// Optimization: Filter and map in single pass to reduce array allocations
let result = ResizeArray<'T>()
let mutable index = 0

for value in elements do
match value with
| JsonValue.Null -> ()
| JsonValue.String s when s |> TextConversions.AsString |> Option.isNone -> ()
| _ ->
result.Add(doc.CreateNew(value, "[" + (string index) + "]") |> mapping.Invoke)
index <- index + 1

result.ToArray()
| JsonValue.Null -> [||]
| x ->
failwithf "Expecting an array at '%s', got %s" (doc.Path())
Expand Down Expand Up @@ -247,9 +254,17 @@ type JsonRuntime =
=
match doc.JsonValue with
| JsonValue.Array elements ->
elements
|> Array.filter (JsonRuntime.Matches cultureStr (InferedTypeTag.ParseCode tagCode))
|> Array.mapi (fun i value -> doc.CreateNew(value, "[" + (string i) + "]") |> mapping.Invoke)
// Optimization: Filter and map in single pass to reduce array allocations
let result = ResizeArray<'T>()
let mutable index = 0
let matchFunc = JsonRuntime.Matches cultureStr (InferedTypeTag.ParseCode tagCode)

for value in elements do
if matchFunc value then
result.Add(doc.CreateNew(value, "[" + (string index) + "]") |> mapping.Invoke)
index <- index + 1

result.ToArray()
| JsonValue.Null -> [||]
| x ->
failwithf "Expecting an array at '%s', got %s" (doc.Path())
Expand Down