diff --git a/Project.toml b/Project.toml index e1d3e64..fdedeba 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "TableView" uuid = "40c74d1a-b44c-5b06-a7c1-6cbea58ea978" -version = "0.6.4" +version = "0.6.5" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" diff --git a/src/TableView.jl b/src/TableView.jl index 7d34d5f..ad966a2 100644 --- a/src/TableView.jl +++ b/src/TableView.jl @@ -7,6 +7,7 @@ using Observables: @map export showtable const ag_grid_imports = [] +const js_max_safe_int = Int128(2^53-1) function __init__() version = readchomp(joinpath(@__DIR__, "..", "ag-grid.version")) @@ -252,32 +253,28 @@ end # directly write JSON instead of allocating temporary dicts etc function table2json(schema, rows, types; requested = nothing) io = IOBuffer() - print(io, '[') + rowwriter = JSON.Writer.CompactContext(io) + JSON.begin_array(rowwriter) + ser = JSON.StandardSerialization() for (i, row) in enumerate(rows) - if requested == nothing || first(requested) <= i <= last(requested) - print(io, '{') - Tables.eachcolumn(schema, row) do val, ind, name - JSON.print(io, name) - print(io, ':') - if val isa Number && isfinite(val) - JSON.print(io, val) - elseif val === nothing - JSON.print(io, repr(nothing)) - elseif val === missing - JSON.print(io, repr(missing)) - else - JSON.print(io, sprint(print, val)) - end - print(io, ',') + if requested != nothing && (i < first(requested) || i > last(requested)) + continue + end + JSON.delimit(rowwriter) + columnwriter = JSON.Writer.CompactContext(io) + JSON.begin_object(columnwriter) + Tables.eachcolumn(schema, row) do val, ind, name + if val isa Real && isfinite(val) && -js_max_safe_int < trunc(Int128, val) < js_max_safe_int + JSON.show_pair(columnwriter, ser, name, val) + elseif val === nothing || val === missing + JSON.show_pair(columnwriter, ser, name, repr(val)) + else + JSON.show_pair(columnwriter, ser, name, sprint(print, val)) end - skip(io, -1) - print(io, '}') - print(io, ',') end + JSON.end_object(columnwriter) end - skip(io, -1) - print(io, ']') - + JSON.end_array(rowwriter) String(take!(io)) end end diff --git a/test/runtests.jl b/test/runtests.jl index f04e4cf..cd933c2 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -32,6 +32,16 @@ end @test firstrow["d"] == 0 @test firstrow["e"] == "test_missing" end +@testset "large integers" begin + rows = Tables.table([2^52 2^53 2^54]) + names = [:a, :b, :c] + types = [Int64 for _ in 1:3] + json = TableView.table2json(Tables.Schema(names, types), rows, types) + firstrow = JSON.parse(json)[1] + @test firstrow["a"] == 4503599627370496 + @test firstrow["b"] == "9007199254740992" + @test firstrow["c"] == "18014398509481984" +end @testset "normal array" begin array = rand(10, 10) @test showtable(array) isa WebIO.Scope