Get the name and the value of every field for an object

I am writing my objects to and from my database. Database columns and field names are matching, so for convenience sake I would like to get an array of fieldnames and an array of field values to pass to the SQL INSERT INTO command. Is this the proper way of doing this task in Julia? I was hoping for some version of the .function operator. Asking to help me learn the language better.

struct Security
    ticker::String
    CUSIP::String
end

security = Security("sdf", "w23423")

julia> fieldnames(jhal.Security)
(:ticker, :CUSIP)

julia> getfield(security, :CUSIP)
"w23423"

julia> map(field -> getfield(security, field), fieldnames(jhal.Security))
("sdf", "w23423")
1 Like

First of all, your approach seems reasonable :+1: probably similar to what I would have done as well.

There is a package which I actually found just when reseaching for this question :wink:
it is NamedTupleTools.jl

With that you could do

using NamedTupleTools
nt = ntfromstruct(security)
keys(nt)
values(nt)

I quite like NamedTuples, they reduce sometimes the amount of structs one needs to define :smiley: so it might be convenient for you too. But maybe it is also overkill here :wink:

(By the way, you probably know it already but it could be that there are already packages which would help you with interfacing with SQL. In particular also DataFrames.jl in case that you haven’t seen it already.)

I think you can do

getfield.(security, fieldnames(jhal.Security))

or

getfield.(security, fieldnames(typeof(security)))

I’m getting a

ERROR: MethodError: no method matching length(::Security)

when trying. Seems

getfield.((security,), fieldnames(Security))

doesn’t raise exception. Is this a version issue?
(I’m on 1.8.0)

Maybe. I didn’t actually test it. I forgot about how structs have a surprising default broadcasting behavior.

I’ve been struggling with the same for a long time, until now that I understood what you need to pass on to the fieldnames() function.

fieldnames() does not accept the object itself as it is called, but the explicit type, then you can check all the fields of an arbitrarily given object by simply making use firs ot typeof():

for instance, to get the fields of the object that is thrown by the constructor of the package ARCHmodels
in their tutorial (Univariate · ARCHModels.jl):

julia> am = UnivariateARCHModel(spec, mydata; dist=StdT(ν), meanspec=Intercept(μ))

you just have to do

julia> fieldnames(typeof(am))

without even know what is the specific way the structure is built (a bit cumbersome for this package)

UnivariateARCHModel{Float64, GARCH{1, 1, Float64}, StdT{Float64}, Intercept{Float64}}

and not transparent about what the names of the fields are.