I'm often deserializing JSONs into Lua tables which leads to tables with lots of nesting levels. When trying to access a non-existing one, Lua will throw the error "attempt to index a nil value". Is there a way to "catch" this error beforehand in order to check if specific table items exist, e.g.
local hello = {}
local v = hello.this.is.a.test
Is there a simple way to check if the item hello.this.is.a.test
exists without manually checking each sub-table in the hierarchy?
I usually write myself a nifty little helper function for this called nilget
(others may call this "delve"):
local function nilget(value, ...)
for i = 1, select("#", ...) do
if value == nil then return nil end
value = value[select(i, ...)]
end
return value
end
In your example, you could use this as nilget(hello, "this", "is", "a", "test")
.
If you want something more similar to the ?.
operator many languages have for this, the closest construct you can get in Lua is (t or {}).k
(which unfortunately, at least in PUC, seems to come at the runtime cost of allocating an empty table if t
is falsey, so don't do this in performance-critical code). Your chain would be pretty verbose if written this way, though: (((((hello or {}).this or {}).is or {}).a or {}).test
.
There's also the option of modifying the metatable of nil
using debug.setmetatable
to just return nil
on indexing. I am just including this for fun (and the sake of completeness); you should not do this in serious code:
debug.setmetatable(nil, {__index = function() end})
After this, (nil).k
will always be nil
in your entire program (VM state), so your chain hello.this.is.a.test
will evaluate without an error even if some items evaluate to nil
.