Skip to content

Support JSON.jl v1 - #521

Draft
fromelicks wants to merge 4 commits into
JuliaGizmos:masterfrom
fromelicks:jsonv1-compat
Draft

fromelicks wants to merge 4 commits into
JuliaGizmos:masterfrom
fromelicks:jsonv1-compat

Conversation

@fromelicks

@fromelicks fromelicks commented Sep 2, 2026 •

Copy link
Copy Markdown

Related to #519 and JuliaGizmos/JSExpr.jl#49.

JSON.jl v1 removed the show_json serialization-context API that JSEvalSerialization was built on (JSON.Writer and JSON.Serializations no longer exist), so WebIO failed to load with UndefVarError: Writer not defined in JSON. Every other JSON API WebIO uses -- json, print, parse, lower, JSONText -- is unchanged.

Split the one affected block on isdefined(JSON, :JSONStyle). On v1, JSEvalSerialization becomes a JSON.JSONStyle and lowers a JSString to a JSONText, which JSON.json writes verbatim -- the same raw splicing the old show_json method did. sort_keys=false keeps object keys in Dict iteration order, since v1 sorts Dict keys by default; this makes the emitted JavaScript byte-identical under either version.

JSON.lower(x::JSString) is deliberately left alone. Lowering it to a JSONText instead would splice JSStrings in raw under the default serialization too, so a node prop such as
Dict("onclick" => js"alert(1)") would serialize to {"onclick":alert(1)} -- not valid JSON. Only JSEvalSerialization splices raw; the new test in test/syntax.jl pins both halves of that.

JSONContext and JSONSerialization alias JSON.jl < 1 internals with no v1 equivalent, so they are defined only on that branch. Likewise verbose_json[], which re-indents a raw fragment across lines, has no v1 equivalent and is documented as < 1 only; nothing in WebIO sets it.

Tested on JSON 0.21.4 and 1.7.1: the pure-Julia part of the suite (node, util, syntax, deprecations, render, asset) passes identically on both, 78 tests each.

@fromelicks

Copy link
Copy Markdown
Author

CI checks fail, probably need #520 or f0440c8

`request` is annotated `AbstractDict` rather than `Dict` because it
comes
straight off the wire: JSON.jl v1 materializes objects as `JSON.Object`,
which is an `AbstractDict` but not a `Dict`. A `Dict` annotation in
`handle_rpc_request` fails to match, and `dispatch_request` turns the
resulting MethodError into an error response, so the RPC silently never
runs.
Under JSON.jl < 1, `JSEvalSerialization <: CommonSerialization` wrote `NaN`, `Inf` and `-Inf` as `null`.
JSON.jl v1 instead throws an ArgumentError, so interpolating e.g. plot data with `NaN` gaps into a `js"..."` literal failed.
Lowered non-finite floats to `nothing` under `JSEvalSerialization` to keep the JSON.jl < 1 output.
Under JSON.jl < 1, `JSON.json` and `JSON.print` wrote `NaN`, `Inf` and `-Inf` as `null`. JSON.jl v1 instead throws an `ArgumentError`, so a `NaN` in an Observable value or a node prop broke messages sent over the Mux and generic HTTP providers as well as rendering nodes and scopes.
Routed these through a new `jsonstring`, which lowers non-finite floats to `nothing` under JSON.jl v1, like `JSEvalSerialization` does for `js"..."` interpolation.

This branch has not been deployed

No deployments
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.

1 participant