Table With Starting With Index Of 0 And Json

I spent a good portion of this evening tearing my hair out, wondering why Corona was blowing out my array when JSON saving and loading a table that has an index of 0.

 

json = require( "json" ) local t, j = {}, {} for i = 0, 10 do t[i] = math.random( 10 ) end print ( "Table size: " .. #t .. " / " .. json.encode( t ) ) saveTable( t, "test.txt" ) j = loadTable( "test.txt" ) print ( "Table size: " .. #j .. " / " .. json.encode( j ) ) print ( j[0] )

 

Using the above code, it will create a table of 11 elements full of random numbers.

 

When run, #t will curiously return a value of 10.

 

But, when you load the same table back into a new variable, the value of #j returns   0.  And, if you attempt to get the value of the j[0], it returns nil.

 

Table size: 10 / {"1":8,"2":2,"3":10,"4":10,"5":8,"6":9,"7":10,"8":3,"9":6,"10":5,"0":3} Table size: 0 / {"1":8,"0":3,"3":10,"2":2,"5":8,"4":10,"7":10,"6":9,"9":6,"8":3,"10":5} nil

 

This is using Daily Build 2013.1053.

I’ve submitted this as a bug  #21777.  Hopefully some light can be shed on this, as I usually create tables that start indexing at 0, and the only way i got it working is by shifting it as one, but then reminding myself to display it as if it’s the zero spot.

Hi there, I don’t think this is necessarily a bug. In JSON, all keys are always enclosed in quotes, i.e., all keys are strings, whereas in Lua, table keys can of course be anything (including numbers, like a traditional array). When you encode a Lua table with numeric indices into JSON, those indices turn into strings, as you can see by the quotes in the keys n the output of your first print statement. When you decode the JSON data back into a Lua table, the table is now one with string indices, not the numerical indices you started with. Since the # notation only returns the number of elements in the numerically indexed part of a table, that explains why it appears there are 10 elements before JSON encoding but 0 after decoding. That’s also why j[0] is returning nil, whereas j[“0”] wouldn’t. As a workaround, if you know you’ll be decoding JSON data with keys that you want to interpret as numbers, immediately after decoding it you could loop through the table using the pairs iterator, and for any key that is the string of a number, put its value the numerical index in the table for that number. - Andrew

Thanks for the clarification, Andrew.

 

I’m not too familiar with the pairs iterator.  Would you happen to be able to provide a code snippet that would reindex them back as numbers?

Hi there,

 

No problem, this code should do the trick.

 

[lua]

 

– Returns a copy of a table where elements with a string index that represents as a number are replaced with elements using a regular number index

local fixTable = function(input)

    local result = {}

    for key,value in pairs(input) do

        if not(tonumber(key) == nil) then

            result[tonumber(key)] = value

        else

            result[key] = input[key]

        end

    end

    

    return result

end

 

json = require( “json” )

 

local t, j = {}, {}

 

for i = 0, 10 do

    t[i] = math.random( 10 )

end

 

print ( "Table size: " … #t … " / " … json.encode( t ) )

 

j = json.decode(json.encode(t))

 

print ( "Table size: " … #j … " / " … json.encode( j ) )

print ( j[0] )

 

j = fixTable(j)

 

print ( "Table size: " … #j … " / " … json.encode( j ) )

print ( j[0] )

[/lua]

Thanks, looks like this will do the trick!

Also see: developer.coronalabs.com/code/dkjson-mixed-indexing

I’ve submitted this as a bug  #21777.  Hopefully some light can be shed on this, as I usually create tables that start indexing at 0, and the only way i got it working is by shifting it as one, but then reminding myself to display it as if it’s the zero spot.

Hi there, I don’t think this is necessarily a bug. In JSON, all keys are always enclosed in quotes, i.e., all keys are strings, whereas in Lua, table keys can of course be anything (including numbers, like a traditional array). When you encode a Lua table with numeric indices into JSON, those indices turn into strings, as you can see by the quotes in the keys n the output of your first print statement. When you decode the JSON data back into a Lua table, the table is now one with string indices, not the numerical indices you started with. Since the # notation only returns the number of elements in the numerically indexed part of a table, that explains why it appears there are 10 elements before JSON encoding but 0 after decoding. That’s also why j[0] is returning nil, whereas j[“0”] wouldn’t. As a workaround, if you know you’ll be decoding JSON data with keys that you want to interpret as numbers, immediately after decoding it you could loop through the table using the pairs iterator, and for any key that is the string of a number, put its value the numerical index in the table for that number. - Andrew

Thanks for the clarification, Andrew.

 

I’m not too familiar with the pairs iterator.  Would you happen to be able to provide a code snippet that would reindex them back as numbers?

Hi there,

 

No problem, this code should do the trick.

 

[lua]

 

– Returns a copy of a table where elements with a string index that represents as a number are replaced with elements using a regular number index

local fixTable = function(input)

    local result = {}

    for key,value in pairs(input) do

        if not(tonumber(key) == nil) then

            result[tonumber(key)] = value

        else

            result[key] = input[key]

        end

    end

    

    return result

end

 

json = require( “json” )

 

local t, j = {}, {}

 

for i = 0, 10 do

    t[i] = math.random( 10 )

end

 

print ( "Table size: " … #t … " / " … json.encode( t ) )

 

j = json.decode(json.encode(t))

 

print ( "Table size: " … #j … " / " … json.encode( j ) )

print ( j[0] )

 

j = fixTable(j)

 

print ( "Table size: " … #j … " / " … json.encode( j ) )

print ( j[0] )

[/lua]

Thanks, looks like this will do the trick!

Also see: developer.coronalabs.com/code/dkjson-mixed-indexing