Can't serialize unitful quantities
Whenever I try to serialize a unitful quantity, I get a stack overflow error.
using JSON3
using Unitful: m
JSON3.write(10m)
yields
ERROR: StackOverflowError:
Stacktrace:
[1] write(::StructTypes.NumberType, buf::Vector{UInt8}, pos::Int64, len::Int64, x::Quantity{Float64, 𝐋, Unitful.FreeUnits{(m,), 𝐋, nothing}})
@ JSON3 ~/.julia/packages/JSON3/CpNms/src/write.jl:225
[2] write(::StructTypes.NumberType, buf::Vector{UInt8}, pos::Int64, len::Int64, x::Quantity{Float64, 𝐋, Unitful.FreeUnits{(m,), 𝐋, nothing}}; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ JSON3 ~/.julia/packages/JSON3/CpNms/src/write.jl:240
--- the last 2 lines are repeated 26659 more times ---
[53321] write(::StructTypes.NumberType, buf::Vector{UInt8}, pos::Int64, len::Int64, x::Quantity{Float64, 𝐋, Unitful.FreeUnits{(m,), 𝐋, nothing}})
@ JSON3 ~/.julia/packages/JSON3/CpNms/src/write.jl:225
julia and package info
julia Version 1.8.3
Commit 0434deb161e (2022-11-14 20:14 UTC)
Platform Info:
OS: Linux (x86_64-linux-gnu)
CPU: 4 × Intel(R) Core(TM) i7-4600U CPU @ 2.10GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-13.0.1 (ORCJIT, haswell)
Threads: 4 on 4 virtual cores
[0f8b85d8] JSON3 v1.12.0
[1986cc42] Unitful v1.12.1
I've narrowed down the problem. JSON3.write assumes that StructType.construct(NT,x) returns an object of type NT (in this case NT==Float64), and Unitful breaks that assumption by defining Float64(x) = Quantity(Float64(x.val), unit(x)).
Hmmmm....I'm struggling to figure out what the right thing to do is for unitful quantities. They overload string to return 10 m, which isn't valid JSON. And you cant' do convert(Float64, x) because you get this cryptic error:
julia> convert(Float64, x)
ERROR: DimensionError: and m are not dimensionally compatible.
Stacktrace:
[1] #s104#159
@ ~/.julia/packages/Unitful/G8F13/src/conversion.jl:12 [inlined]
[2] var"#s104#159"(::Any, s::Any, t::Any)
@ Unitful ./none:0
[3] (::Core.GeneratedFunctionStub)(::Any, ::Vararg{Any})
@ Core ./boot.jl:602
[4] uconvert(a::Unitful.FreeUnits{(), NoDims, nothing}, x::Unitful.Quantity{Int64, 𝐋, Unitful.FreeUnits{(m,), 𝐋, nothing}})
@ Unitful ~/.julia/packages/Unitful/G8F13/src/conversion.jl:78
[5] convert(#unused#::Type{Float64}, y::Unitful.Quantity{Int64, 𝐋, Unitful.FreeUnits{(m,), 𝐋, nothing}})
@ Unitful ~/.julia/packages/Unitful/G8F13/src/conversion.jl:145
[6] top-level scope
@ REPL[10]:1
It seems like probably the most robust solution would be to do an extension package where we write unitful quantities as JSON strings and then hopefully there's a way to parse unitful quantities?