Caution: JSON.decode() can kill your tables elements...

I just ran across something that I don’t know the best way to code around…

If you write a function to write convert a table to JSON and write the resulting string to a file and then read it back in, it’s ok… 

If you add a table element “foo” for example to the table and read it back in, foo is gone. The JSON code overwrites the new definition of the table (without foo) and replaces it with the one that was saved.

            local contents = file:read( "\*a" )             AppSettings = json.decode(contents);

The only way I can think of to load a previously saved table into the new one is to read it into a temp table and copy every element in the temp table to the active table.

I can’t test for the foo element in the table because it isn’t even there.

Is there a way to test to see if foo exists in a table?

So, if you release an update and you have this save / restore function built in, how can you make sure the next rev does not lose the elements that were added to the table to make the next rev?

Any suggestions?

Perhaps there should be a non-destructive version of json.decode() that would parse the table string and apply the values in the string, and not kill the previous table elements, unless they are overwritten by data in the JSON string?

What I do is every time I add or change something in my settings, I immediately write it out to the file so that the file is the latest settings.  json.decode is going to replace the table.  That’s what it does.

If you want to work around this you can json.decode to a temporary table, then run a :

    for k, v in pairs(tmpTable) do

          realtable[k] = v

    end

to copy the elements to the real table.

(note: untested code)

Rob, 

Your solution won’t work if you have a table within a table. You have to do a deep copy so that any tables enclosed inside will copy. Perhaps in the near future we will have a version that provides a safe decode option from the original JSON developer. 

Thanks!
Stu

What I’ve done is to include a version code in my appSettings table. I also have a hardcoded version code variable in my module which I increment every time I change the structure of my appSettings. After reading in the appSettings table from the device, I check the version code against  the hardcoded one to see if any changes need to be made. 

If the two are different I pass the appSettings table to a verification function which checks the table and inserts any missing data, and then saves the table back to the device with the modified table.

What I do is every time I add or change something in my settings, I immediately write it out to the file so that the file is the latest settings.  json.decode is going to replace the table.  That’s what it does.

If you want to work around this you can json.decode to a temporary table, then run a :

    for k, v in pairs(tmpTable) do

          realtable[k] = v

    end

to copy the elements to the real table.

(note: untested code)

Rob, 

Your solution won’t work if you have a table within a table. You have to do a deep copy so that any tables enclosed inside will copy. Perhaps in the near future we will have a version that provides a safe decode option from the original JSON developer. 

Thanks!
Stu

What I’ve done is to include a version code in my appSettings table. I also have a hardcoded version code variable in my module which I increment every time I change the structure of my appSettings. After reading in the appSettings table from the device, I check the version code against  the hardcoded one to see if any changes need to be made. 

If the two are different I pass the appSettings table to a verification function which checks the table and inserts any missing data, and then saves the table back to the device with the modified table.