JSON Decode Loop Problem

Hi everyone,

So I am pulling my hair out over this. Hope someone can help.

I have successfully implemented the Firebase plugin, and I have data in my Firebase database. I am now trying to get data back from the Firebase database. 

The problem is that when I decode the JSON data, and loop through it (using kev/value pairs iteration), it looks like this in the console:

Pablo table: 0x7ffc8d14ab40

GGEspresso table: 0x7ffc8d14a090

Here is my code:

myNewData = e.response local myTable = json.decode(myNewData) for key,value in pairs(myTable) do -- for k,v in pairs(value) do print(key,value) -- end end print( "---------------------" ) end end)

Even if I drill down further, by adding another for loop :

myNewData = e.response local myTable = json.decode(myNewData) for key,value in pairs(myTable) do for k,v in pairs(value) do -- This is the new for loop print(key,value) end end print( "---------------------" ) end end)

It gets data, but I still have other nested tables that show up as table: 0x7ffc8d14ab40

What am I doing wrong? I want to loop through all tables (and nested tables) in one iteration loop.

Any help would be greatly appreciated!

Thanks!

You can drill down with code, but you need something a little more generic. Typically you’ll do this via a stack

stack[#stack + 1] = t -- Put table on top -- do something with it stack[#stack] = nil -- pop it

or recursion (calling the function on itself). The latter is probably easier in this situation. You’d want something like:

local function PrintTable (t, indent, already\_visited) if already\_visited then if already\_visited[t] then print(indent .. "CYCLE:", t) -- mention it, but don't visit it return else already\_visited[t] = true end end for k, v in pairs(t) do print(indent, k, v) if type(v) == "table" then PrintTable(v, indent .. " ", already\_visited) -- Drill down! end end end function Print (t, might\_have\_cycles) -- I assume JSON won't encode data with cycles, but just in case :) local already\_visited if might\_have\_cycles then already\_visited = {} -- keep track of tables so we don't get caught in loops end PrintTable(t, "", already\_visited) end

(Untested, but the general idea would be the same.) Then just call it like

Print(my\_table)

Also, somewhere in the blog there’s an article about a table printer, along with a forum post or two. Various printers exist in the wild, too.

You can use print_r from here:

https://github.com/roaminggamer/SSKLegacy/blob/master/ssk/extensions/table.lua

-- == -- table.print\_r( theTable ) - Dumps indexes and values inside multi-level table (for debug) -- == table.print\_r = function ( t ) --local depth = depth or math.huge local print\_r\_cache={} local function sub\_print\_r(t,indent) if (print\_r\_cache[tostring(t)]) then print(indent.."\*"..tostring(t)) else print\_r\_cache[tostring(t)]=true if (type(t)=="table") then for pos,val in pairs(t) do if (type(val)=="table") then print(indent.."["..pos.."] =\> "..tostring(t)) print(indent.."{") --sub\_print\_r(val,indent..string.rep(" ",string.len(pos)+6)) sub\_print\_r(val,indent..string.rep(" ",3)) --print(indent..string.rep(" ",string.len(pos)+1).."}") print(indent..string.rep(" ",0).."}") elseif (type(val)=="string") then print(indent.."["..pos..'] =\> "'..val..'"') else print(indent.."["..pos.."] =\> "..tostring(val)) end end else print(indent..tostring(t)) end end end if (type(t)=="table") then print(tostring(t).." {") sub\_print\_r(t," ") print("}") else sub\_print\_r(t," ") end end

NOTE: Probably pretty similar to Steve’s post.

You guys are legends! Thanks!! 

So I can’t seem to iterate over the list with a normal “for” loop:

for i = 1, #myTable do print(myTable[i]) end

Its printing nothing. I need to access the data because I want to add it to a tableView (and pass through the params):

 for i = 1, #myTable do tableView:insertRow{ rowHeight = 158, isCategory = false, rowColor = { 0, 1, 1 }, lineColor = { 0.90, 0.90, 0.90, 0 }, params = { image = myTable[i].image, name = myTable[i].name, address = myTable[i].address, } end

Any idea where I am going wrong?

Thanks!

for k,v in pairs( myTable ) do print(k,v) end

Thanks! That did work. I had to drill deeper in order to pass the right params:

    for k,v in pairs( myTable ) do 

        for key, value in pairs(v) do

I was hoping I would be able to just use a normal for loop. This will work though.

Thanks again! Much appreciated!

You can drill down with code, but you need something a little more generic. Typically you’ll do this via a stack

stack[#stack + 1] = t -- Put table on top -- do something with it stack[#stack] = nil -- pop it

or recursion (calling the function on itself). The latter is probably easier in this situation. You’d want something like:

local function PrintTable (t, indent, already\_visited) if already\_visited then if already\_visited[t] then print(indent .. "CYCLE:", t) -- mention it, but don't visit it return else already\_visited[t] = true end end for k, v in pairs(t) do print(indent, k, v) if type(v) == "table" then PrintTable(v, indent .. " ", already\_visited) -- Drill down! end end end function Print (t, might\_have\_cycles) -- I assume JSON won't encode data with cycles, but just in case :) local already\_visited if might\_have\_cycles then already\_visited = {} -- keep track of tables so we don't get caught in loops end PrintTable(t, "", already\_visited) end

(Untested, but the general idea would be the same.) Then just call it like

Print(my\_table)

Also, somewhere in the blog there’s an article about a table printer, along with a forum post or two. Various printers exist in the wild, too.

You can use print_r from here:

https://github.com/roaminggamer/SSKLegacy/blob/master/ssk/extensions/table.lua

-- == -- table.print\_r( theTable ) - Dumps indexes and values inside multi-level table (for debug) -- == table.print\_r = function ( t ) --local depth = depth or math.huge local print\_r\_cache={} local function sub\_print\_r(t,indent) if (print\_r\_cache[tostring(t)]) then print(indent.."\*"..tostring(t)) else print\_r\_cache[tostring(t)]=true if (type(t)=="table") then for pos,val in pairs(t) do if (type(val)=="table") then print(indent.."["..pos.."] =\> "..tostring(t)) print(indent.."{") --sub\_print\_r(val,indent..string.rep(" ",string.len(pos)+6)) sub\_print\_r(val,indent..string.rep(" ",3)) --print(indent..string.rep(" ",string.len(pos)+1).."}") print(indent..string.rep(" ",0).."}") elseif (type(val)=="string") then print(indent.."["..pos..'] =\> "'..val..'"') else print(indent.."["..pos.."] =\> "..tostring(val)) end end else print(indent..tostring(t)) end end end if (type(t)=="table") then print(tostring(t).." {") sub\_print\_r(t," ") print("}") else sub\_print\_r(t," ") end end

NOTE: Probably pretty similar to Steve’s post.

You guys are legends! Thanks!! 

So I can’t seem to iterate over the list with a normal “for” loop:

for i = 1, #myTable do print(myTable[i]) end

Its printing nothing. I need to access the data because I want to add it to a tableView (and pass through the params):

 for i = 1, #myTable do tableView:insertRow{ rowHeight = 158, isCategory = false, rowColor = { 0, 1, 1 }, lineColor = { 0.90, 0.90, 0.90, 0 }, params = { image = myTable[i].image, name = myTable[i].name, address = myTable[i].address, } end

Any idea where I am going wrong?

Thanks!

for k,v in pairs( myTable ) do print(k,v) end

Thanks! That did work. I had to drill deeper in order to pass the right params:

    for k,v in pairs( myTable ) do 

        for key, value in pairs(v) do

I was hoping I would be able to just use a normal for loop. This will work though.

Thanks again! Much appreciated!