loadsave is saving my table's numeric indexes as strings

I’m not sure what I changed that is causing this, but suddenly the numeric indexes of a table I’m saving with loadsave are being loaded by loadTable() as string keys. The data is correct at the time of being saved AND the data is successfully read in from that file, but the numeric keys become string keys.
 
That is, rather than this (which is expected):

data[1]

It is loading as:

data['1']

Which is obviously wrong. It makes things like ipairs() fail since after loading there are no numeric keys.

This is the filename code:

function level\_data.getFilename(category)     return 'level\_data' .. category .. '.json' end

This is the loading code:

function level\_data.load(category)     local data = loadsave.loadTable(level\_data.getFilename(category))     if not data then         data = {             category = category         }     end      -- This is just a test; as of right now, this is not printing anything   for k, v in ipairs(data) do         print(k, v)     end -- This one DOES print stuff, but the "numeric" keys are in random order (with -- category in the middle) since they are strings for k, v in pairs(data) do         print(k, v)     end -- This always prints zero print(#data)     for level = 1, #levels[category], 1 do -- This condition is always firing since level is an integer but the -- table is being loaded with strings         if not data[level] then             data[level] = {                 unlocked = false             }         end     end     return data end

This is the saving code:

function level\_data.save(data) -- This always prints the correct number of levels in the data print(#data)     loadsave.saveTable(data, level\_data.getFilename(data.category)) end

What’s going on? This has been working for me for a long time, I’m not sure why loadsave is suddenly doing this.

If you JSON encode a table like this:

local myTable = {} myTable[1] = "Bob" myTable.sex = "Male"

then decode it, you’ll get a table like this:

local myTable = {} myTable["1"] = "Bob" myTable["sex"] = "Male"

i.e. All of the indexes will be converted to strings.

There is no getting around this.  It is a side-effect of mixing index types.

You can however repair the indexes like this:

local myTable = {} myTable["1"] = "Bob" myTable["sex"] = "Male" local function repairIndexes( tbl ) local newtbl = {} for k,v in pairs(tbl) do if( tonumber(k) ~= nil ) then newtbl[tonumber(k)] = v else newtbl[k] = v end end return newtbl end myTable = repairIndexes( myTable )

Perfect explanation, that’s very clear now. Thanks to that I was able to solve this issue by removing the “category” item from the table, and now it uses numeric indexes like I had intended. Many thanks!

EDIT: And that code for converting string indexes to numeric will likely come in very handy down the road, thank you for that as well!

If you JSON encode a table like this:

local myTable = {} myTable[1] = "Bob" myTable.sex = "Male"

then decode it, you’ll get a table like this:

local myTable = {} myTable["1"] = "Bob" myTable["sex"] = "Male"

i.e. All of the indexes will be converted to strings.

There is no getting around this.  It is a side-effect of mixing index types.

You can however repair the indexes like this:

local myTable = {} myTable["1"] = "Bob" myTable["sex"] = "Male" local function repairIndexes( tbl ) local newtbl = {} for k,v in pairs(tbl) do if( tonumber(k) ~= nil ) then newtbl[tonumber(k)] = v else newtbl[k] = v end end return newtbl end myTable = repairIndexes( myTable )

Perfect explanation, that’s very clear now. Thanks to that I was able to solve this issue by removing the “category” item from the table, and now it uses numeric indexes like I had intended. Many thanks!

EDIT: And that code for converting string indexes to numeric will likely come in very handy down the road, thank you for that as well!