JSON.json writes an empty `Vector{Union{}}` as `{}` instead of `[]`
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 82/100
Research direction
Read the arraylike method in src/write.jl and find the tests for JSON serialization of vectors. Check how empty Vector{Union{}} values are classified, then verify they serialize as [] and nested empty vectors as [[]] while vectors of Pairs still serialize as objects.
Written by the indexing model from the issue text.
Description
An empty vector whose element type is Union{} is written as a JSON object instead of an array:
julia> using JSON # v1.10.0
julia> JSON.json(Union{}[])
"{}"
julia> JSON.json([Union{}[]])
"[{}]"
julia> JSON.json(Any[]) # for comparison
"[]"
Expected: "[]" and "[[]]".
In practice this shows up when serializing values parsed by JSON3.jl, which types every empty array as JSON3.Array{Union{}, …}, so a JSON3 → JSON.jl round trip turns empty arrays into objects:
julia> using JSON3
julia> JSON.json(JSON3.read("""{"a":[],"b":[[]],"c":[1]}"""))
"{\"a\":{},\"b\":[{}],\"c\":[1]}"
JSON 0.21.4 writes [] in all of these cases. I see the new behaviour on 1.8.0, 1.9.0 and 1.10.0 (Julia 1.13.1).
Cause
src/write.jl writes vectors of Pairs as objects:
StructUtils.arraylike(::JSONStyle, x::AbstractVector{<:Pair}) = false
Union{} is a subtype of every type, so Vector{Union{}} <: AbstractVector{<:Pair} is true, and empty Union{}-element vectors dispatch to this method:
julia> Vector{Union{}} <: AbstractVector{<:Pair}
true
julia> which(JSON.StructUtils.arraylike, (JSON.JSONWriteStyle, Vector{Union{}}))
arraylike(::JSON.JSONStyle, x::AbstractVector{<:Pair}) @ JSON src/write.jl:140
Possible fix
A more specific method restores array output and leaves the Pair behaviour alone:
StructUtils.arraylike(::JSONStyle, ::AbstractVector{Union{}}) = true
With that defined:
julia> JSON.json(Union{}[]), JSON.json([Union{}[]]), JSON.json([:a => 1])
("[]", "[[]]", "{\"a\":1}")
- Dominant language
- Julia
- Stars
- 359
- Forks
- 116
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 11
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from JuliaIO/JSON.jl
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
JuliaIO/JSON.jl#492 · 1 comment ·
Maintainers usually reply within 1 day
-
Method ambiguity for custom types with generically defined `StructUtils.StructStyle` methodsPossibly taken @quinnj claimed this 128 days ago. Open
Difficulty 3/5 1-2 days Newbie friendliness 55/100
JuliaIO/JSON.jl#464 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 38/100
JuliaIO/JSON.jl#433 · 3 comments ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 50/100
JuliaIO/JSON.jl#415 · 2 comments ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 25/100
JuliaIO/JSON.jl#377 · 14 comments · 2 reactions ·
Maintainers usually reply within 1 day
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
SciML/PETScDiffEq.jl#196 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 1-3 hours Newbie friendliness 84/100
SciML/Catalyst.jl#1571 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
SciML/Optimization.jl#1414 ·
Maintainers usually reply within 1 day