Need to save your game data in Corona SDK? Check out this little bit of code.

Posted by & filed under Tech Geek.

A very frequent question in the Corona SDK Forums is “How do I save my game data?”.  There are several published solutions in the Community Code and while I they are good, they don’t help you learn how to program or carry extra functions that you may not need.

I (and several other’s) frequently suggest “Just use JSON!”.  But in a recent post in the forums, I realized that as simple as this really is, the language encouraged people to go look up JSON with the concept that they needed to learn JSON.  JSON or JavaScript Object Notation, is a simple syntax for encoding data in a light-weight standard way.  You can dig into the guts of JSON at

The typical JSON file is considerably smaller than the same data encoded in XML and it’s a great way to represent table data like in a language like Lua, which Corona SDK.

If you click through to the links above, you may be immediately intimidated, in fact so intimidated that you are turned off to the concept of using JSON.  But here is the beauty with Lua and Corona SDK, you don’t need to know JSON at all.  In fact it may be a bit better if you just accept that Corona provides you two API calls and assume that everything else is simply magic.

To see just how simple this is, check out this code.  But before I present this code, some of it may still be scary and that is the code to open a file and to read and write files.  However, it’s important to learn this code because as you work on other apps, you will need to read and write files to the file system.

Mobile applications run in a “Sandbox”, which is a protected area.  You can only access files inside your space only.  There are typically four specific locations where files are stored and retrieved from.  They include:

  • The Resource Folder (called a Directory)
  • The Documents Directory
  • The Temporary Directory
  • The Cache Directory

The Resources directory, which Corona SDK,  calls:  system.ResourcesDirectory,  is basically your application files that are “bundled” together and installed on your device.  This frequently referred to as the “app bundle”.  These file can be read only and not written to.  This is for security to prevent malware from infecting your app.

The Documents Directory is where you store your permanent files.  In Corona SDK, this is known as system.DocumentsDirectory.  Any file that your app needs to run that cannot be re-created gets saved here.  It should be noted that Apple with iOS 5 and iCloud, files in this folder get automatically backed up to iCloud.  Corona SDK currently does not give us an option to turn off those backups.  Apple is cracking down on downloaded files, that can be reproduced being saved in this directory since iCloud’s “free” space is limited and they don’t want it full of game code, graphics and other downloaded directory.

Because of this we now have the Caches directory or system.CachesDirectory.  This is a folder to store these downloaded files that can be re-downloaded.  In most senses, you “cache” files that you download that doesn’t change frequently and only download the files when they change.  Web browsers help websites load faster by keeping images, CSS and JavaScript files around on your computer so they don’t have to reload them over the Internet.  You’re app should do the same thing for files that you download.   Files in this folder **CAN** be deleted by the system if the overall file storage gets too low, but they for the most part should remain from session to session, but can be re-downloaded if necessary.

The final location to store files is the Temporary directory or system.TemproaryDiretory.  This is where you put files you don’t care about from session to session.

Files in general require three operations:

  • Open the file
  • Read or write data to/from the file
  • Close the file

Corona SDK uses some syntax for processing files that’s a bit confusing.  After a year of working with the product, I still have to look up the file operation API calls, so don’t worry if you don’t get this code right away.

-- load the JSON library.
local json = require("json")

-- Function to save a table.  Since game settings need to be saved from session to session, we will
-- use the Documents Directory

local json = require("json")
function saveTable(t, filename)
local path = system.pathForFile( filename, system.DocumentsDirectory)
local file =, "w")
if file then
local contents = json.encode(t)
file:write( contents )
io.close( file )
return true
return false

function loadTable(filename)
local path = system.pathForFile( filename, system.DocumentsDirectory)
local contents = ""
local myTable = {}
local file = path, "r" )
if file then
-- read all contents of file into a string
local contents = file:read( "*a" )
myTable = json.decode(contents);
io.close( file )
return myTable
return nil

So while we are using JSON to format the data when we save it and read it back in, you have to learn ZERO JSON to use this. It magically turns a Lua table into a string that can be then written to a file. If you read that string back in, then decode it with json.decode you end up with the exact came table you started with.

Then to use this magic, you simply do:

myGameSettings = {}
myGameSettings.highScore = 1000
myGameSettings.soundOn = true
myGameSettings.musicOff = true
myGameSettings.playerName = "Barney Rubble"
saveTable(myGameSettings, "mygamesettings.json")

To read your game settings:

myGameSettings = loadTable("mygamesettings.json")

While you’re getting two very simple, easy to use calls that you really don’t have to think about, please take time to learn what those two functions are doing with regards to opening, reading, writing and closing files. You can save learning the JSON format until another day.

Corona SDK excels in letting you do complex tasks in simple easy ways. We don’t think twice about what’s under the hood of the display.newImageRect() API call. You don’t need to think about what’s under the hood with JSON either.

This code can be downloaded from Github.

46 Responses to “Need to save your game data in Corona SDK? Check out this little bit of code.”

  1. Rodrigo RSCdev

    Hi Rob!

    As a big fan of your knowledge and your WAY to explain the code (as Mrs. Peach does so well too), I only would like to say a big thank you for posting this great topic and all the awesome helps on CoronaSDK Forums as well.

    Best Regards,

  2. Noah

    Ha! Glad my forum post could inspire this article. What a great help this is!
    Thanks again!

  3. Danny

    This was a fantastic help to me! Thanks a bazillion! :-D (Official number! ;-P )

    One little query – shouldn’t the load line be:

    [quote] myGameSettings = loadTable(“mygamesettings.json”) [/quote]

    instead of :

    [quote] mySettings = loadTable(“mygamesettings.json”) [/quote]

    Otherwise it doesn’t work for me. But worked when I changed it as above.

  4. Gary

    You missed a “t” in settings in the sample save code

  5. Mario

    Epic sir! Man, you are going straight into my RSS feeds for Corona. I don’t know WHY I haven’t done so already. And looking forward to reading about the RESTful integration too! Thanks Rob!

  6. Emanouel

    thanks rob for the great lesson.

    how do i go about outputting the highScore onto the screen? and also have it update while moving around the storyboard?


  7. Robin Hood

    thanks for the awesome post.

    one question here, how can i encrypt the contents saving to json file then decrypt again when read the file.

    thanks in advance.

  8. EHO

    This is killer. I set this up and was saving and loading data in about 2.5 minutes flat. I did take the time to better understand the io API. It would have been solvable for me to set up on my own but your solution strikes me as excellent and certainly saved me a number of hours of work.

    For anyone that is new to working with system information, I got some forum help that explained you can use the File -> Show Project Sandbox to find the folder on your machine that keeps the system.DocumentsDirectory content for your Corona Simulator work.

    Thanks for the nice article and the code :)

  9. Rob Miracle

    I guess it depends on how you want to encrypt it, but you could take the JSON output which is just a text string, then encrypt the whole thing, then create a new json structure that is just the one variable:

    $data = json_encode($array);
    $edata = encrypt($data);

    or something similar.

  10. Mike Kelly

    hi Rob,
    I asked this in a reply to one of your posts in another forum. I need an answer relatively quickly so I’m trying you here as well. sorry… what I need to know is how one can email the contents of a table (specifically a photo captured by an iPhone in an app). but since I’m here, does json allow you to upload image data as well?

  11. Satwant


    Thank you soo much for pointing out the file > show project sandbox. I am new to lua so that reallllyyy helped!

    Fantastic code aswell =D

  12. fernando

    Hello Rob, with this method, can save also the score, and load in others levels?

  13. hallmark

    Thanks for this article. It is very helpful.

    The data that we store by this method, will it persist and stay if we launch an app update?

    I am saving scores using your method and I do-not want them to be overwritten when I launch an app update

  14. Hamza

    Hi Rob,
    I am now also a great fan of your knowledge. But I have a problem when I implement this, it works great on simulator, but on device, that scene could not be open where I READ or WRITE data, app neither crashes nor open that scene, just stucked.
    What I have done, made a class of this code, and use that class by “local json = require “jsonCustomClass””, and using jsonCustomClass.saveTable(…) and jsonCustomClass.loadTable(…)
    Can you help me out and tell me what I am doing wrong?

  15. Rob Miracle

    Updates don’t overwrite data. It only gets erased if they delete the app or wipe the device

  16. jeff

    Hi sorry I am newbie in corona, I dont know how to use ‘ur file

    I try to create myTable.json same folder with all lua file, and in main.lua I add this

    local loadsave = require “loadsave” –loadsave.lua in samefolder

    myTable = {}
    myTable.musicOn = false
    myTable.soundOn = true

    loadsave.saveTable(myTable, “myTable.json”)

    but when I run the program, nothing happen, I thought it suppose save value on

    myTable.musicOn = false
    myTable.soundOn = true


    please help me to understand, thx

  17. Rob Miracle

    Well first of all, you cannot save data to the same folder your main.lua is in. That is known as system.ResourcesDirectory and is READ-ONLY. You can load a JSON table from there, but you cannot write one. By default the code listed here reads/writes from your sandboxed folder known as system.DocumentsDirectory. This is the natural place to save settings too. I know some people have modified this to support reading/writing from system.TemporaryDirectory and system.CachesDirectory.

    It’s not designed to work with the same folder your main.lua is in.

  18. Tom Knutsen

    Hi Rob!

    First of all, thank you for everything you do to help us struggling indie developers ;)

    I have been saving and loading like a champ for a while now, but today I got a problem. Everything has worked great for a long time, but suddenly my json file is overwritten even if I dont save it?!?!

    It happens when I change scenes in storyboard. When I create the json file in the first scene, all information is stored as it should. When I change to the next scene, the information is ereased but the json file is still there. The strange thing is that I dont have any function for this json file in the next scene :( I have created three json files in the first scene but only one json file gets the information ereased.

    Have you any idea what could be the problem?

    Thanx :D

  19. Tom Knutsen


    I cheated a little.
    I had to use in the next scene as well and retype the information and save it again in the json file.

    Really strange :-/

  20. Ovidiu

    Hey Rob!

    First of all I’d like to thank you for all your tutorials, thanks to you and others like you I’ve managed to make my first game but I still have tons more things to learn regarding corona and game development in general. I’ve always managed to find the answers to the questions I had in forums and tutorials but this time I’m stumped. I just don’t get how to use Json and that’s why I’m asking for your help now.

    Here is the scenario:

    I have the main.lua which takes me to the start.lua (it has the title and a start game button) which takes me to the afterstart.lua (it has for now just a level select button) which takes me to the levelSelect.lua (it has a list of the available levels, some being locked); after this are the levels 1,2,3… After each level is completed the next level is unlocked.

    What I want to save for now is the level statuses, locked or unlocked, and I don’t understand where I have to put any of the code you wrote above. I mean what do I have to write in the main.lua or in the levelSelect.lua, do I have to make a new .lua file for the Json code?

    Sorry for the noob question but I didn’t know where else to turn.

    Thanks in advance

  21. Rob Miracle

    There are really two parts to this:

    1. Putting these two functions somewhere that you can access them from any of your scenes.
    2. Storing the data you want to save in a Lua table (that is probably accessible from any scene)

    Lets attack the 2nd one first. A few weeks ago Corona Labs posted a blog called Goodbye Globals ( that discusses a technique of creating a lua module called mydata.lua that holds an empty table that you can use to pass data around instead of using Globals. I would advise reading this and implementing it. Because you may have data in this table that you DONT want to save, you probably should have a sub-table called gameSettings:

    mydata.gameSettings = {}
    mydata.gameSettings.musicOn = true
    mydata.gameSettings.highScore = 0

    etc. You can put in whatever data you need to track your level status (score per level, stars earned, unlocked or not, etc) into a table inside of mydata.gameSettings. The idea here is that gameSettings holds everything and only the things you want to save.

    Then you can call saveTable by simply passing it the mydata.gameSettings table. i.e.:

    saveTable(mydata.gameSettings, “settings.json”)

    You don’t really need to know any JSON, that’s what this function does for you.

    Now to get this function where you can find it. I normally have another .lua file that I call “utility.lua”. This is where I stick all my misc code and I just add these as functions in there and return the module:

    local M = {}
    function M.saveTable()


    function M.loadTable


    return M

    of course you have to put the code for those functions in the above snippet. Now I would just do a:

    local utility = require(“utility”)

    in each place where I need to save the table and then the all (if you do both is)

    utility.saveTable(mydata.gameSettings, “settings.json”)

    Typically you only need to load the table when the app first starts up, so you would do:

    mydata.gameSettings = utility.loadTable(“settings.json”)

  22. nowfal

    I got an error ” unexpected symbol near ‘T'” when using json load and save functions, can you help me?

  23. Ovidiu

    Thanks for the help Rob. I had a lot of trouble understanding how and what at first but after a lot of trial and error I finally got it to work.
    You’re doing us all a huge favor.


  24. Rob Miracle

    How are you calling the saveTable function? Make sure you’re not passing a nil value for your table to save.

  25. Ovidiu


    I had the same error and found that it was because I copy/pasted
    utility.saveTable(mydata.gameSettings, “settings.json”). where “settings.json” isn’t the same as “settings.json”. The quote signs are different in the first case and they are not recognized.
    At least that’s why I got that error.

  26. luanoob

    This is great. I’m looking to add to a list of data (like a history list of data created) instead of just overwriting a single value. Could you point me in the right direction to accomplish that?

    On that note, are there limits/gotchas when writing/reading a growing json file?


  27. Raul

    hello there i am new hear on this blog.

    i have some questions about one game that i am trayng to change the value high score and its not working can some one help me pleas the name game is clash of clans and its on android device. you can se short movies on YouTube about this game allot of people tried things and its not working

    Big 10X for the help and have nice day

  28. james

    sir i am a newbie in corona but i’ll try to learn some hardcoded code in corona.but this code of high score is working in corona and for android also.

  29. Mike Kelly

    hi Rob,
    I’m loading videos into a game accompanied by questions. when the person gets the answer correct based on the video they just watched, I don’t want that video to play again, but to skip to the next one. I was thinking of trying to store the correctly answered videos in a json file, and setting up a conditional to check the json file to see if it was there and if so to bypass it. Is this a reasonable approach: How would I check for particular strings? Or are there any examples you know of that have accomplished something similar? My research has turned up nothing. Would a table set up in a myData.lua file to store a series of strings be a better option? If so, how would I access from the table, something like if the table correctVideos contains “videos1/video11.m4v” then videoView:load(“videos1/video”..”1″..myData.score1 + (1)..”.m4v”) Hope this makes sense…Thanks, Rob!

  30. sbk

    Can you clarify what you meant about iCloud and the documents directory? Should we not store small local data there? Your code showed storing to the documents directory, but then you mentioned the cache directory and Apple’s restrictions. Thank you.

  31. Rob Miracle

    Basically, Apple doesn’t want anything that can be downloaded or recreated to be put in the system.DocumentsDirectory because those files end up getting backed up by iCloud. Small data files that are important to the running of the app are perfectly fine to put in the system.DocumentsDirectory. If you look at native.setSync() it will show you the code to allow you to write larger files to system.DocumentsDirectory and not have them backed up.

  32. Carlos Antunes

    Hello Rob, thank you a lot for the help with the code.
    I just have a question, if I would like to print on the screen some score data that is stored on my json file, should I convert the type of my data to screen?

    local music=display.newText(“”..tostring(myTable.musicOn),40,0)

    It works and is displayed on the screen but than if I want to change this data I receive some error. Would I have to convert it again to the type it was before so I can work with it and not with a strin?
    If not, there is any easier way to print on the screen the data stored on my json file?

    Thank you again!!!!

  33. Rob Miracle

    If myTable.musicOn is a boolean (true/false), then really the best way to do this is:

    local music
    if myTable.musicOn then
    music = display.newText("On", 40, 0)
    music = display.newText("Off", 40, 0)

    Then if you want to change the value of myTable.musicOn then you can just change it to true or false as necessary.

  34. Josh

    Hi Rob –

    Everytime I close my app out and reopen it my highscore gets erased and set back to zero. As long as I don’t close the app the highscore stays. Can you help explain to me how to permanently keep the highscore even after the app is closed?

    in utility.lua I have copied your code exactly as show above:

    local json = require(“json”)

    function saveTable(t, filename)

    function loadTable(filename)

    highscore = {}

    highscore.level1 = 0
    highscore.level2 = 0

    saveTable(highscore, “highscore.json”)

    then in my game.lua I have:

    local json = require(“json”)

    local utility = require(“utility”)

    highscore = loadTable(“highscore.json”)

    levelhighscore = highscore.level1

    if score > highscore then
    highscore.level1 = score

    I’ve discovered that if I change the name of my saveTable in my utility.lua then it works…but only after the highscore.json in in my sandbox. If I delete highscore.json then out of my sandbox, then it doesn’t work again…unless I first change my saveTable in my utility.lua back to the original name. I’m caught in this loop of how do I get it to work the FIRST time and not erase data after that?

    I hope that makes sense. Thanks in advance for your help.

  35. idan

    It dosent work for me. i have savedData.lua :

    local json = require(“json”)
    local savedData = {}

    savedData.saveTable = function(t, filename)
    local path = system.pathForFile( filename, system.DocumentsDirectory)
    local file =, “w”)
    if file then
    local contents = json.encode(t)
    file:write( contents )
    io.close( file )
    return true
    return false
    savedData.loadTable = function(filename)
    local path = system.pathForFile( filename, system.DocumentsDirectory)
    local contents = “”
    local myTable = {}
    local file = path, “r” )
    if file then
    — read all contents of file into a string
    local contents = file:read( “*a” )
    myTable = json.decode(contents);
    io.close( file )
    return myTable
    return nil

    and im using it in play.lua just to check it :

    local savedData = require(‘savedData’)
    highScore = {}
    highScore[1] = 1000
    highScore[2] = 2000
    savedData.saveTable(highScore , “highScore.json”)

    and i have error: error loding module ‘savedData’ from file ‘savedData.lua’
    savedData.lua:19 unexpected simbol near ‘?’

Leave a Reply

  • (will not be published)

XHTML: You can use these tags: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">