Trying to figure out how to save data (json)

I’ve been using the tutorial found here: https://coronalabs.com/blog/2014/10/14/tutorial-saving-and-loading-lua-tables-with-json/

I have a table called playerData that I use to save all key factors of the game (how much money the player has, the level they are on, etc…)

I have downloaded the file as mentioned under the “Table load/save functions” and I have included it in my project folder as well as every .lua file that I plan on triggering the save function and the load function.

in my main.lua file I have this code (only place I plan to load the playerData)

playerData = loadsave.loadTable( "playerData.json" ) if ( playerData == nil ) then print("Nil info on data table seemed to not have loaded...") end 

pretty much in every .lua file that has the ability to change any of the info in the playerData table, I also trigger the following code to save

loadsave.saveTable( playerData, "playerData.json" )

I have recently started testing my app on my physical device. I have noticed that when I close out of the app completely on my device and load it up again, nothing has saved.

I would love it if I could get some help as to what I am doing wrong here.

Thanks

Note: when I test the app on the corona simulator (so I can see the console outputs) It does NOT output the nil print value I have set up for the load.

I also added a print(“load success”) and print(“save success”)  inside each of the loadsave functions that are referenced and I see the success message whenever I load the app on the corona simulator

Do you have your app initializing the table or are you expecting the file to already exist in system.DocumentsDirectory?

Normally in main.lua you would do something like:

myData.settings = utility.loadTable("settings.json") if myData.settings == nil then myData.settings = {} myData.settings.shipsOwned = { true, true, false, true, false, false, false, false } myData.settings.shipInUse = 1 myData.settings.bank = 1000 myData.settings.unlockedLevels = 3 myData.settings.highScore = 0 myData.settings.levels = {} myData.settings.firstRun = true utility.saveTable( myData.settings, "settings.json") end

In fact that’s copy/pasted from a game I’m working on. I’m using the myData concept from: http://coronalabs.com/blog/2013/05/28/tutorial-goodbye-globals/ and the “settings” sub-table is what I save out. But in main.lua you need to try and read the file. If you get nil, then create a table with your initial values and then save the table out. This will create the first version in system.DocumentsDirectory. When you build your app, you’re only getting what’s in system.ResourcesDirectory. It doesn’t install anything out of your simulator’s system.DocumentsDirectory (or Temporary or Caches) to the device.

Rob

well, I have a file called playerData.lua that would show something similar to what you posted.

I do call it practically in the first line of my main.lua file

This is my main.lua file

print(display.imageSuffix) print(display.actualContentWidth) math.randomseed( os.time() ) local playerData = require("Scripts.playerData") local loadsave = require("loadsave") playerData = loadsave.loadTable( "playerData.json" ) if ( playerData == nil ) then print("Nil info on data table seemed to not have loaded...") end local composer = require("composer") composer.gotoScene( "Scripts.logoScreen", {effect = "fade", time = 500} )

I would assume, that the first ever time the app launches it would load the playerData with the default info I had set.

As you play the game the values on the playerData table change and are saved in the JSON format. When you load the app for the second time it would load the “default” playerData table that I have, but as soon as it comes to the loadTable function it would then overwrite the default playerData with the playerData info saved through JSON.

I must be thinking of this all wrong though because its obviously not working.

There is another current forum thread talking about essentially the same thing. I’d give it a look over and try to decrease your project’s code to ensure that you are creating the .json file correctly, then start adding the rest of your code back in:

https://forums.coronalabs.com/topic/65137-json-file-being-read-in-simulator-but-not-on-device/

Had this issue been solved ???

local playerData = require("Scripts.playerData") playerData = loadsave.loadTable( "playerData.json" ) if ( playerData == nil ) then print("Nil info on data table seemed to not have loaded...") end

Perhaps you’re using “playerData” for two different things.  In the first case, you’re loading a .lua file from the “Scripts” folder named playerData.lua. When you get to your device things become case sensitive. Are you sure “Scripts” is “Scripts” and not “scripts” in the file system? Is it playerData.lua and not playerdata.lua?  These files are in your app’s project folder or what we refer to as system.ResourcesDirectory. This content is read only.

What is the purpose of this playerData.lua file?

You immediately write over whatever table playerData.lua returned with the table of the JSON data it decoded from playerData.json which is stored in system.DocumentsDirectory in your apps sandbox. On the first run this file doesn’t exist so you’re in effect making playerData nil. Later if you try to add items to the table, it should cause runtime errors. 

From what I see above you should:

  1. Stop using playerData for two different things. If they are the same thing, you can’t require the saved table.

  2. Make sure you’re matching the case exactly on the file names.

  3. When you detect that you were unable to load the settings, create a table, populate it with your default saved data and save it immediately like in the example I posted above.

  4. In other places where you’re saving the settings, make sure the file name matches the same case as you’re trying to load.

Rob

Note: when I test the app on the corona simulator (so I can see the console outputs) It does NOT output the nil print value I have set up for the load.

I also added a print(“load success”) and print(“save success”)  inside each of the loadsave functions that are referenced and I see the success message whenever I load the app on the corona simulator

Do you have your app initializing the table or are you expecting the file to already exist in system.DocumentsDirectory?

Normally in main.lua you would do something like:

myData.settings = utility.loadTable("settings.json") if myData.settings == nil then myData.settings = {} myData.settings.shipsOwned = { true, true, false, true, false, false, false, false } myData.settings.shipInUse = 1 myData.settings.bank = 1000 myData.settings.unlockedLevels = 3 myData.settings.highScore = 0 myData.settings.levels = {} myData.settings.firstRun = true utility.saveTable( myData.settings, "settings.json") end

In fact that’s copy/pasted from a game I’m working on. I’m using the myData concept from: http://coronalabs.com/blog/2013/05/28/tutorial-goodbye-globals/ and the “settings” sub-table is what I save out. But in main.lua you need to try and read the file. If you get nil, then create a table with your initial values and then save the table out. This will create the first version in system.DocumentsDirectory. When you build your app, you’re only getting what’s in system.ResourcesDirectory. It doesn’t install anything out of your simulator’s system.DocumentsDirectory (or Temporary or Caches) to the device.

Rob

well, I have a file called playerData.lua that would show something similar to what you posted.

I do call it practically in the first line of my main.lua file

This is my main.lua file

print(display.imageSuffix) print(display.actualContentWidth) math.randomseed( os.time() ) local playerData = require("Scripts.playerData") local loadsave = require("loadsave") playerData = loadsave.loadTable( "playerData.json" ) if ( playerData == nil ) then print("Nil info on data table seemed to not have loaded...") end local composer = require("composer") composer.gotoScene( "Scripts.logoScreen", {effect = "fade", time = 500} )

I would assume, that the first ever time the app launches it would load the playerData with the default info I had set.

As you play the game the values on the playerData table change and are saved in the JSON format. When you load the app for the second time it would load the “default” playerData table that I have, but as soon as it comes to the loadTable function it would then overwrite the default playerData with the playerData info saved through JSON.

I must be thinking of this all wrong though because its obviously not working.

There is another current forum thread talking about essentially the same thing. I’d give it a look over and try to decrease your project’s code to ensure that you are creating the .json file correctly, then start adding the rest of your code back in:

https://forums.coronalabs.com/topic/65137-json-file-being-read-in-simulator-but-not-on-device/

Had this issue been solved ???

local playerData = require("Scripts.playerData") playerData = loadsave.loadTable( "playerData.json" ) if ( playerData == nil ) then print("Nil info on data table seemed to not have loaded...") end

Perhaps you’re using “playerData” for two different things.  In the first case, you’re loading a .lua file from the “Scripts” folder named playerData.lua. When you get to your device things become case sensitive. Are you sure “Scripts” is “Scripts” and not “scripts” in the file system? Is it playerData.lua and not playerdata.lua?  These files are in your app’s project folder or what we refer to as system.ResourcesDirectory. This content is read only.

What is the purpose of this playerData.lua file?

You immediately write over whatever table playerData.lua returned with the table of the JSON data it decoded from playerData.json which is stored in system.DocumentsDirectory in your apps sandbox. On the first run this file doesn’t exist so you’re in effect making playerData nil. Later if you try to add items to the table, it should cause runtime errors. 

From what I see above you should:

  1. Stop using playerData for two different things. If they are the same thing, you can’t require the saved table.

  2. Make sure you’re matching the case exactly on the file names.

  3. When you detect that you were unable to load the settings, create a table, populate it with your default saved data and save it immediately like in the example I posted above.

  4. In other places where you’re saving the settings, make sure the file name matches the same case as you’re trying to load.

Rob