Skip to content

Enhance compatibility with StaticArrays.jl #429

@hyrodium

Description

@hyrodium

It would be great if JSON.parse could support parsing directly into StaticArrays.jl static arrays. For example, it would be nice if the following worked:

julia> using JSON, StaticArrays

julia> JSON.parse("[1,2]", Vector{Int})
2-element Vector{Int64}:
 1
 2

julia> JSON.parse("[1,2]", SVector{2,Int})
ERROR: MethodError: Cannot `convert` an object of type UndefInitializer to an object of type Int64
The function `convert` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  convert(::Type{T}, ::T) where T<:Number
   @ Base number.jl:6
  convert(::Type{T}, ::Number) where T<:Number
   @ Base number.jl:7
  convert(::Type{T}, ::T) where T
   @ Base Base_compiler.jl:133
  ...

Stacktrace:
  [1] macro expansion
    @ ~/.julia/packages/StaticArraysCore/7xxEJ/src/StaticArraysCore.jl:88 [inlined]
  [2] convert_ntuple
    @ ~/.julia/packages/StaticArraysCore/7xxEJ/src/StaticArraysCore.jl:84 [inlined]
  [3] SVector{2, Int64}(x::Tuple{UndefInitializer, Int64})
    @ StaticArraysCore ~/.julia/packages/StaticArraysCore/7xxEJ/src/StaticArraysCore.jl:120
  [4] StaticArray
    @ ~/.julia/packages/StaticArrays/DsPgf/src/convert.jl:173 [inlined]
  [5] initialize
    @ ~/.julia/packages/StructUtils/CvpPP/src/StructUtils.jl:172 [inlined]
  [6] makearray(style::JSON.JSONReadStyle{JSON.Object{String, Any}, Nothing}, ::Type{SVector{2, Int64}}, source::JSON.LazyValue{String})
    @ StructUtils ~/.julia/packages/StructUtils/CvpPP/src/StructUtils.jl:873
  [7] make(style::JSON.JSONReadStyle{JSON.Object{String, Any}, Nothing}, T::Type, source::JSON.LazyValue{String})
    @ StructUtils ~/.julia/packages/StructUtils/CvpPP/src/StructUtils.jl:779
  [8] _parse
    @ ~/.julia/packages/JSON/0oqO1/src/parse.jl:193 [inlined]
  [9] parse(x::JSON.LazyValue{String}, ::Type{SVector{…}}; dicttype::Type{JSON.Object{…}}, null::Nothing, style::JSON.JSONReadStyle{JSON.Object{…}, Nothing})
    @ JSON ~/.julia/packages/JSON/0oqO1/src/parse.jl:189
 [10] parse
    @ ~/.julia/packages/JSON/0oqO1/src/parse.jl:189 [inlined]
 [11] parse(buf::String, ::Type{SVector{…}}; dicttype::Type{JSON.Object{…}}, null::Nothing, style::JSON.JSONReadStyle{JSON.Object{…}, Nothing}, kw::@Kwargs{})
    @ JSON ~/.julia/packages/JSON/0oqO1/src/parse.jl:181
 [12] parse(buf::String, ::Type{SVector{2, Int64}})
    @ JSON ~/.julia/packages/JSON/0oqO1/src/parse.jl:181
 [13] top-level scope
    @ REPL[3]:1
Some type information was truncated. Use `show(err)` to see complete types.

I found that defining the following method makes it work:

julia> StructUtils.makearray(style, T::Type{<:StaticVector}, source) = T([source[i][] for i in 1:length(T)]), StructUtils.applyeach(style, StructUtils.ArrayClosure(eltype(T)[], style), source)

julia> JSON.parse("[1,2]", SVector{2,Int})
2-element SVector{2, Int64} with indices SOneTo(2):
 1
 2

However, I’m not sure which function would be the appropriate extension point for this. It’s also unclear to me which package should provide this support — JSON.jl, StaticArrays.jl, or possibly even StructUtils.jl. In any case, this would likely need to be implemented as a package extension. Since StructUtils.makearray does not appear to be documented, I’m not sure whether it is considered internal API.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions