Search code examples
lua

Is there a way to check if an arbitrary table item exists?


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?


Solution

  • 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.