I'm new to lua and having a hard time with working with nested data structures.
I am trying to write a hierarchy system where I have a table of three keys and the values are another table. The three top level keys are zone, region and environment in order of specificness for me. I want to use the most specific subvalue that is present in the table that is related to the keys of my environment variables.
So given the table of data and environment variables below, I want to return the key for region.US since the zone variable does not exist in the table, although if it did that would be top priority. The key region.US does exist and is a higher priority than environment, therefore I should return ccc.
Depending on how lua loads up the table, I get different results by string matching the top level key. How can I do this in Lua?
env_zone = 5 -- doesn't exist in table, but should return if it did
env_region = US -- exists and should return because env_zone doesn't exist
env_environment = food -- does exist but should not be returned because env_region is a higher priority
zone:
1: aaaaa
2: bbbbb
region:
EU: ddd
US: ccc
environment:
food: gggg
prod: eee
staging: fff
My code that doesn't work properly.
local cjson = require('cjson')
function tprint (tbl, indent)
if not indent then indent = 0 end
for k, v in pairs(tbl) do
formatting = string.rep(" ", indent) .. k .. ": "
if type(v) == "table" then
print(formatting)
tprint(v, indent+1)
elseif type(v) == 'boolean' then
print(formatting .. tostring(v))
else
print(formatting .. v)
end
end
end
local function slurp(path)
local f = io.open(path)
local s = f:read("*a")
f:close()
return s
end
local json_string = slurp("data.json")
local tab = cjson.decode(json_string)
local zone_var = os.getenv("zone") -- "fake"
local region_var = os.getenv("region") -- "US"
local env_var = os.getenv("env") -- "food"
local ok, err = pcall(
function ()
for key, value in pairs(tab) do
if string.match(key, "zone") then --highest priority, check it first
for subkey, subvalue in pairs(value) do
if string.match(subkey, zone_var) then
print(subvalue)
return
end
end
elseif string.match(key, "region") then --second highest priority
for subkey, subvalue in pairs(value) do
if string.match(subkey, region_var) then
print(subvalue)
return
end
end
elseif string.match(key, "environment") then --last chance
for subkey, subvalue in pairs(value) do
if string.match(subkey, env_var) then
print(subvalue)
return
end
end
end
end
end
)
tprint(tab)
Outputs: Should always be returning ccc
➜ lua git:(integration) ✗ lua test1.lua
gggg
environment:
staging: fff
prod: eee
food: gggg
zone:
2: bbbbb
1: aaaaa
region:
US: ccc
EU: ddd
...
➜ lua git:(integration) ✗ lua test1.lua
ccc
zone:
1: aaaaa
2: bbbbb
region:
EU: ddd
US: ccc
environment:
food: gggg
prod: eee
staging: fff