I have a Dict from parsing a JSON message, and want to convert it into a struct.
This works:
using StaticArrays
const MyFloat = Float64
sys_state_dict = Dict(:time => 0,
:t_sim => 0,
:sys_state => 0,
:e_mech => 0,
:orient => [0.530989, 0.466959, -0.466959, -0.530989],
:elevation => 1.2426,
:azimuth => 0,
:l_tether => 150,
:v_reelout => 0,
:force => 559.847,
:depower => 0.25,
:steering => 0,
:heading => 0,
:course => 0,
:v_app => 12.5799,
:vel_kite => [0, 0, 0],
:X => Union{Float64, Int64}[0, 8.90221, 17.5546, 25.9174, 33.9673, 41.687, 49.0618, 49.2317, 50.7465, 50.4513, 50.4513],
:Y => Union{Float64, Int64}[0, 0, 0, 0, 0, 0, 0, 0, 0, 2.84247, -2.84247],
:Z => Union{Float64, Int64}[0, 23.41, 46.9136, 70.5217, 94.2383, 118.064, 142.0, 147.029, 149.031, 146.739, 146.739]
)
P = 11
mutable struct SysState{P}
"time since start of simulation in seconds"
time::Float64
"time needed for one simulation timestep"
t_sim::Float64
"state of system state control"
sys_state::Int16
"mechanical energy [Wh]"
e_mech::Float64
"orientation of the kite (quaternion, order w,x,y,z)"
orient::MVector{4, Float32}
"elevation angle in radians"
elevation::MyFloat
"azimuth angle in radians"
azimuth::MyFloat
"tether length [m]"
l_tether::MyFloat
"reel out velocity [m/s]"
v_reelout::MyFloat
"tether force [N]"
force::MyFloat
"depower settings [0..1]"
depower::MyFloat
"steering settings [-1..1]"
steering::MyFloat
"heading angle in radian"
heading::MyFloat
"course angle in radian"
course::MyFloat
"norm of apparent wind speed [m/s]"
v_app::MyFloat
"velocity vector of the kite"
vel_kite::MVector{3, MyFloat}
"vector of particle positions in x"
X::MVector{P, MyFloat}
"vector of particle positions in y"
Y::MVector{P, MyFloat}
"vector of particle positions in z"
Z::MVector{P, MyFloat}
end
function sys_state_dict2struct(sys_state_dict)
SysState{P}(sys_state_dict[:time],
sys_state_dict[:t_sim],
sys_state_dict[:sys_state],
sys_state_dict[:e_mech],
sys_state_dict[:orient],
sys_state_dict[:elevation],
sys_state_dict[:azimuth],
sys_state_dict[:l_tether],
sys_state_dict[:v_reelout],
sys_state_dict[:force],
sys_state_dict[:depower],
sys_state_dict[:steering],
sys_state_dict[:heading],
sys_state_dict[:course],
sys_state_dict[:v_app],
sys_state_dict[:vel_kite],
sys_state_dict[:X],
sys_state_dict[:Y],
sys_state_dict[:Z]
)
end
sys_state_dict2struct(sys_state_dict)
But it is error prone, because if I make a change to the struct I also have to make a manual change to the function sys_state_dict2struct()
.
How can I avoid that?
Not working:
using StaticArrays, StructTypes, JSON3
const MyFloat = Float64
sys_state_dict = Dict(:time => 0,
:t_sim => 0,
:sys_state => 0,
:e_mech => 0,
:orient => [0.530989, 0.466959, -0.466959, -0.530989],
:elevation => 1.2426,
:azimuth => 0,
:l_tether => 150,
:v_reelout => 0,
:force => 559.847,
:depower => 0.25,
:steering => 0,
:heading => 0,
:course => 0,
:v_app => 12.5799,
:vel_kite => [0, 0, 0],
:X => Union{Float64, Int64}[0, 8.90221, 17.5546, 25.9174, 33.9673, 41.687, 49.0618, 49.2317, 50.7465, 50.4513, 50.4513],
:Y => Union{Float64, Int64}[0, 0, 0, 0, 0, 0, 0, 0, 0, 2.84247, -2.84247],
:Z => Union{Float64, Int64}[0, 23.41, 46.9136, 70.5217, 94.2383, 118.064, 142.0, 147.029, 149.031, 146.739, 146.739]
)
P = 11
mutable struct SysState{P}
"time since start of simulation in seconds"
time::Float64
"time needed for one simulation timestep"
t_sim::Float64
"state of system state control"
sys_state::Int16
"mechanical energy [Wh]"
e_mech::Float64
"orientation of the kite (quaternion, order w,x,y,z)"
orient::MVector{4, Float32}
"elevation angle in radians"
elevation::MyFloat
"azimuth angle in radians"
azimuth::MyFloat
"tether length [m]"
l_tether::MyFloat
"reel out velocity [m/s]"
v_reelout::MyFloat
"tether force [N]"
force::MyFloat
"depower settings [0..1]"
depower::MyFloat
"steering settings [-1..1]"
steering::MyFloat
"heading angle in radian"
heading::MyFloat
"course angle in radian"
course::MyFloat
"norm of apparent wind speed [m/s]"
v_app::MyFloat
"velocity vector of the kite"
vel_kite::MVector{3, MyFloat}
"vector of particle positions in x"
X::MVector{P, MyFloat}
"vector of particle positions in y"
Y::MVector{P, MyFloat}
"vector of particle positions in z"
Z::MVector{P, MyFloat}
end
StructTypes.StructType(::Type{SysState{P}}) = StructTypes.Mutable()
function sys_state_dict2struct(sys_state_dict)
JSON3.read(sys_state_dict, SysState{P})
end
sys_state_dict2struct(sys_state_dict)
This fails with the error message:
ERROR: LoadError: MethodError: no method matching read(::Dict{Symbol, Any}, ::Type{SysState{11}})
Closest candidates are:
read(::StructTypes.NumberType, ::Any, ::Any, ::Any, ::Any, ::Type{Integer}; kw...)
@ JSON3 ~/.julia/packages/JSON3/jSAdy/src/structs.jl:67
read(::StructTypes.NumberType, ::Any, ::Any, ::Any, ::Any, ::Type{Real}; kw...)
@ JSON3 ~/.julia/packages/JSON3/jSAdy/src/structs.jl:65
read(::StructTypes.NumberType, ::Any, ::Any, ::Any, ::Any, ::Type{Union{Bool, T}}; kw...) where T<:Real
@ JSON3 ~/.julia/packages/JSON3/jSAdy/src/structs.jl:61
...
Stacktrace:
[1] sys_state_dict2struct(sys_state_dict::Dict{Symbol, Any})
@ Main ~/repos/KiteViewers.jl/mwes/mwe_09.jl:72
[2] top-level scope
@ ~/repos/KiteViewers.jl/mwes/mwe_09.jl:75
[3] include(fname::String)
@ Base.MainInclude ./client.jl:489
[4] top-level scope
@ REPL[1]:1
in expression starting at /home/ufechner/repos/KiteViewers.jl/mwes/mwe_09.jl:75
Any idea?