Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve show for nested Objects #301

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Conversation

joshday
Copy link

@joshday joshday commented Dec 8, 2024

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)

@joshday
Copy link
Author

joshday commented Dec 18, 2024

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)

test/runtests.jl Outdated Show resolved Hide resolved
@joshday
Copy link
Author

joshday commented Dec 18, 2024

I'm opting for Base.show(io::IO, o::Object) = JSON3.write(io, o)

It seems the least disruptive and still a win.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants