Improve show for nested Objects
This PR improves the usefulness and performance of Base.show-ing nested JSON3.Objects.
Here's an example with the Plotly.JS schema. It takes several seconds to show the Object, and no information about the nested objects has been provided:
path = download("https://github.com/plotly/plotly.js/raw/v2.35.2/dist/plot-schema.json");
obj = JSON3.read(read(path));
@time display(obj) # warmup
@time display(obj)
# JSON3.Object{Vector{UInt8}, Vector{UInt64}} with 7 entries:
# :animation => {…
# :config => {…
# :defs => {…
# :frames => {…
# :layout => {…
# :traces => {…
# :transforms => {…
# 3.476441 seconds (157.89 M allocations: 8.390 GiB, 11.97% gc time)
With this PR:
@time display(obj)
#JSON3.Object{Vector{UInt8}, Vector{UInt64}} with 7 entries:
# :animation => { direction, frame, fromcurrent, mode, transition }
# :config => { autosizable, displaylogo, displayModeBar, doubleClick, doubleClickDelay…
# :defs => { editType, impliedEdits, metaKeys, valObjects }
# :frames => { items, role }
# :layout => { layoutAttributes }
# :traces => { bar, barpolar, box, candlestick, carpet, choropleth, choroplethmap, cho…
# :transforms => { aggregate, filter, groupby, sort }
# 0.003864 seconds (18.37 k allocations: 1.214 MiB)
Note that the top level show method uses show(::IO, ::MIME"text/plain", ::AbstractDict) and nested objects use show(::IO, ::Object).
This will break any downstream code that relied on Base.show(::IO, ::Object) to generated valid JSON. If valid JSON is a requirement I'd propose changing Base.show(io::IO, obj::Object) = JSON3.write(io, obj). It's still slow at about 1 second, but it at least would show some of the contents:
julia> @time display(obj)
#JSON3.Object{Vector{UInt8}, Vector{UInt64}} with 7 entries:
# :animation => {"direction":{"description":"The direction in which to play the frames tr…
# :config => {"autosizable":{"description":"Determines whether the graphs are plotted …
# :defs => {"editType":{"layout":{"description":"layout attributes should include an…
# :frames => {"items":{"frames_entry":{"baseframe":{"description":"The name of the fra…
# :layout => {"layoutAttributes":{"_deprecated":{"title":{"description":"Value of `tit…
# :traces => {"bar":{"animatable":true,"attributes":{"_deprecated":{"bardir":{"descrip…
# :transforms => {"aggregate":{"attributes":{"aggregations":{"items":{"aggregation":{"edit…
# 0.894440 seconds (38.21 M allocations: 1.984 GiB, 9.98% gc time)
Failing CI looks unrelated to this PR (Some Int64 vs Int32 error for Arrow compatibility on Windows, invalid kwarg to makedocs in the Documenter build)
I'm opting for Base.show(io::IO, o::Object) = JSON3.write(io, o)
It seems the least disruptive and still a win.