using YAML, StructTypes, Parameters
@with_kw struct Test
can_log::String
sys_log::String
version::String
info::String
end
data = YAML.load_file("data/config.yaml")
test = data["tests"][1]
println(test)
and data (config.yaml):
tests:
- can_log: data/27-08-2022/logfile.csv
sys_log: data/27-08-2022/syslog
version: 1.7.1
info: first test
- can_log: data/28-08-2022/logfile.csv
sys_log: data/28-08-2022/syslog
version: 1.7.2
info: second test
If I run the script the output is:
julia> test
Dict{Any, Any} with 4 entries:
"sys_log" => "data/27-08-2022/syslog.csv"
"can_log" => "data/27-08-2022/logfile.csv"
"version" => "1.7.1"
"info" => "first test"
How can I convert this dict into a struct of the type Test ?
StructTypes.Mutable() requires an empty constructor in the type, Test() = new(). StructTypes.Struct() doesn’t require it, and is also an option here, if the YAML files can be relied upon to always provide these four fields.
Though slightly less performant than StructTypes.Struct, Mutable is a much more robust method for mapping Julia struct fields for serialization. …
This flow has the nice properties of: allowing object construction success even if fields are missing in the input, and if “extra” fields exist in the input that aren’t apart of the Julia struct’s fields, they will automatically be ignored. This allows for maximum robustness when mapping Julia types to arbitrary data foramts that may be generated via web services, databases, other language libraries, etc.
(in short, StructTypes.Struct is slightly more performant, but StructTypes.Mutable is more robust to data issues in the input YAML file.)
It seems the keys have to be Symbols for the construction to work. Either convert them after reading:
test = Dict(Symbol(k) => v for (k, v) in data["tests"][1])
or read them in as Symbols in the first place:
julia> data = YAML.load_file("filename.yml"; dicttype=Dict{Symbol,Any})
Or the complete code that converts an array of dicts from YAML to an array of structs in Julia:
using YAML, StructTypes
mutable struct Test
can_log::String
sys_log::String
version::String
info::String
Test() = new()
end
StructTypes.StructType(::Type{Test}) = StructTypes.Mutable()
const tests = Test[]
data = YAML.load_file("data/config.yaml"; dicttype=Dict{Symbol,Any})
for test_dict in data[:tests]
test = StructTypes.constructfrom(Test, test_dict)
push!(tests, test)
end
tests