json encode/decode - Unexpected Side-effect

I recently encountered an odd (to me) behavior with the json library.

I use json encode() and decode() as part of my process for saving and restoring tables to/from disk.

table ==> json.encode() ==> io.write() … io.read() ==> json.decode() ==> table

The issue I ran into was, when I tried saving and restoring a table with mixed indices.

If you use json encode()/decode() on a table with mixed indicies like this:
[lua]local json = require “json”

local t = { }

t[1] = “Corona”
t.totally = “Rocks”

local j = json.encode( t )

local t2 = json.decode( j )[/lua]

What you will get back in t2 is a table indexed with all strings. i.e. Whereas I started with one numeric index and one string index, I got back two string indexes.

[lua]for k,v in pairs(t) do
print ( k … " : " … type(k) … " : " … v … " : " … type(v))
end

– 1 : number : Corona : string
– totally : string: Corona : string

for k,v in pairs(t2) do
print ( k … " : " … type(k) … " : " … v … " : " … type(v))
end

– 1 : string : Corona : string
– totally : string: Corona : string[/lua]

So, if you use json encode() and decode() a lot, beware this side-effect. It isn’t much of a suprise once you think about how encode must have been implemented, but still it caught me by suprise when I tried to index a table using numbers and it had been converted to string indexes.

Oh, and if anyone has a cool way of solving this, please let me know. [import]uid: 110228 topic_id: 33276 reply_id: 333276[/import]

All,

I have a easy solution for this if anyone finds themselves needing it. It isn’t elegant, but it is fast enough.

Continuing from the code in my first post the fix would do this…
[lua]for k,v in pairs( t2) do
if( tonumber(k) ) then
t2[k] = nil
t2[tonumber(k)] = v
end
end

for k,v in pairs(t2) do
print ( k … " : " … type(k) … " : " … v … " : " … type(v))
end

– 1 : number: Corona : string
– totally : string: Rocks : string[/lua]

Warning - all of my my last lines should have been: [lua]-- totally : string: Rocks : string[/lua] I typoed that in my original post.

The one thing that still bugs me a little is that I expected lua to automatically consider a string containing a number to be a number and find values in a table using either a number or a ‘stringized’ number. i.e. I figured t2[1] to behave the same as t2[“1”], but alas it did not. :frowning: [import]uid: 110228 topic_id: 33276 reply_id: 132219[/import]

I had same problem a while back.
See: developer.coronalabs.com/code/dkjson-mixed-indexing
Suhada :wink:
[import]uid: 67842 topic_id: 33276 reply_id: 132255[/import]

All,

I have a easy solution for this if anyone finds themselves needing it. It isn’t elegant, but it is fast enough.

Continuing from the code in my first post the fix would do this…
[lua]for k,v in pairs( t2) do
if( tonumber(k) ) then
t2[k] = nil
t2[tonumber(k)] = v
end
end

for k,v in pairs(t2) do
print ( k … " : " … type(k) … " : " … v … " : " … type(v))
end

– 1 : number: Corona : string
– totally : string: Rocks : string[/lua]

Warning - all of my my last lines should have been: [lua]-- totally : string: Rocks : string[/lua] I typoed that in my original post.

The one thing that still bugs me a little is that I expected lua to automatically consider a string containing a number to be a number and find values in a table using either a number or a ‘stringized’ number. i.e. I figured t2[1] to behave the same as t2[“1”], but alas it did not. :frowning: [import]uid: 110228 topic_id: 33276 reply_id: 132219[/import]

I had same problem a while back.
See: developer.coronalabs.com/code/dkjson-mixed-indexing
Suhada :wink:
[import]uid: 67842 topic_id: 33276 reply_id: 132255[/import]

Sweet! Thanks for this suggestion. [import]uid: 110228 topic_id: 33276 reply_id: 132379[/import]

Sweet! Thanks for this suggestion. [import]uid: 110228 topic_id: 33276 reply_id: 132379[/import]