Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 13 of 13
  1. #1
    New to the CF scene
    Join Date
    May 2013
    Posts
    3
    Thanks
    2
    Thanked 0 Times in 0 Posts

    using JSON as database

    Hi all!

    Need a little help here: I need to use a .json file instead of a SQL Database (for framework reasons). Its gonna be a highscore database for a mobile game and looks like so (example data):

    Code:
    {"Highscores":[
        {"Name":"Marina","Time":"2:30","Points":1320},
        {"Name":"Stefano","Time":"2:32","Points":1319},
        {"Name":"Christine","Time":"1:30","Points":2435},
        {"Name":"Michael","Time":"3:42","Points":878},
        {"Name":"Myriam","Time":"1:55","Points":2590},
        ]}
    Now I need to READ and WRITE into that "database" but have no clue how to do this. I managed to insert a row like this:

    Code:
    function setHighscore(newtime, newhighscore, newname) {
    
            //open highscore.json
            var dh = Stream.openFile(this._datei,"r");
    
            var jsonobject=parseData(dh);//h.toString();
            dh.close;
    
           //set new values
            jsonobject["Highscores"][5]["Time"]=newtime;
            jsonobject["Highscores"][5]["Points"]=newhighscore;
            jsonobject["Highscores"][5]["Name"]=newname;
    
           
            var dh2 = Stream.openFile(this._datei,"w+");
            dh2.printf("%v",jsonobject);
            dh2.close();
        }
    however this only works if I have an empty data-record on position "5" which will then be filled. But I want it to append whatever new values to the END of the array. since the highscore database will be growing it should determine the last position and insert the new values accordingly.

    Next thing, I also need to display the "Top Ten" of this database on a seperate screen. Im a noob so please bear with me. This is what I tried to retrieve data:

    Code:
    function getHighscore(nr) {
            
            //TODO: Exceptions
            var dh = Stream.openFile(this._datei,"r");
            //Parse JSON File
    
            var data = parseData(dh);
            //return data
            console << data["Highscores"][nr-1]["Time"];
            //dh.print(text);
            dh.close;
        }
    this works fine for just one parameter (in this case Time) but as soon as I add the other ones (name, points) it returns "undefined". What am I doing wrong here?

    btw Im using Moscrif framework which is a JavaScript derivate...but very similar to it.

    many thanks in advance

  • #2
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,020
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    You can write into the *in-memory* copy of that data, and you could even save the changed data to a cookie or to local storage.

    But that means that NOBODY except the person on whose computer you made the change will ever see the change.

    Assuming you want this as a database that can be seen by more than one person, you have no choice but to use SOME kind of server.

    Moscrif supporsts SQLLite (which, by the way, would be a better choice than your JSON idea), but again that is on the *client* and no other users can see changes.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • Users who have thanked Old Pedant for this post:

    tchintchie (05-20-2013)

  • #3
    Senior Coder Dormilich's Avatar
    Join Date
    Jan 2010
    Location
    Behind the Wall
    Posts
    3,133
    Thanks
    12
    Thanked 332 Times in 328 Posts
    just to mention a server-side, JSON-type, NoSQL DB: MongoDB
    The computer is always right. The computer is always right. The computer is always right. Take it from someone who has programmed for over ten years: not once has the computational mechanism of the machine malfunctioned.
    Andr Behrens, NY Times Software Developer

  • Users who have thanked Dormilich for this post:

    tchintchie (05-20-2013)

  • #4
    New to the CF scene
    Join Date
    May 2013
    Posts
    3
    Thanks
    2
    Thanked 0 Times in 0 Posts
    thanks to all for your quick replies. Old-Pedant: yes I know Moscrif offers SQLite which was our initial choice. But during the process of our development they decided to take it from the free version :-( since this is a school project we cant afford the basic version that includes SQLite. A local storage would be a sufficient solution at the moment though.

  • #5
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,020
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    Well, I still say a server-side solution would be better.

    MySQL and PHP are both free, for example. And it's pretty easy to get PHP to produce JSON output that your JS code could then consume.

    But in any case, your manipulation of the data once it is in JS is wrong.

    Code:
    function setHighscore(newtime, newhighscore, newname) {
    
            //open highscore.json
            var dh = Stream.openFile(this._datei,"r");
    
            var highscores = parseData(dh);//h.toString();
            dh.close;
    
           //set new values
           var obj = new Object;
           obj["Time"]=newtime;
           obj["Points"]=newhighscore;
           obj["Name"]=newname;
           highscores.push( obj ); // append to end of existing array 
    
         ...
    You will pardon me if I changed the name of your "jsonobject" to something that better describes the purpose.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #6
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,020
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    I also do *NOT* like your JSON data, in the first place.

    This would be a much more reasonable implementation:
    Code:
    {
        "Highscores": {
            "Marina" : { "Time":"2:30","Points":1320 },
            "Stefano" : { "Time":"2:32","Points":1319},
            "Christine" : { "Time":"1:30","Points":2435},
            "Michael" : { "Time":"3:42","Points":878},
            "Myriam" : { "Time":"1:55","Points":2590}
        }
    }
    Let's say you wanted to find the number of points scored by "Michael".

    With your implementation, you would have to do:
    Code:
         var points = null;
         for ( var ix = 0; ix < jsonobject.length; ++ix )
         {
            if ( jsonobject[ix]["Name"] == "Michael" ) points = jsonobject[ix]["Points"];
         }
         if ( points == null ) alert("No points found for Michael");
    With my implementation you would simply do
    Code:
        var person = highscores["Michael"];
        var points = person == null ? null : person.Points;
         if ( points == null ) alert("No points found for Michael");
    Why use an array instead of nested objects?
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #7
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,020
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    Oh, and if you do that, then you could easily implement your function as
    Code:
    function setHighscore(newtime, newhighscore, name) 
    {
            //open highscore.json
            var dh = Stream.openFile(this._datei,"r");
    
            var highscores = parseData(dh);//h.toString();
            dh.close;
    
           //set new values
           if ( highscores[name] == null ) highscores[name] = new Object;
           highscores[name].Points = newhighscore;
           highscores[name].Time = newtime;
           
           ...
    Or, even better, if you don't know if newhighscore is really higher than the existing high score:
    Code:
    function setNewHighscoreOnlyIfHigher(newtime, newhighscore, name) 
    {
            //open highscore.json
            var dh = Stream.openFile(this._datei,"r");
    
            var highscores = parseData(dh);//h.toString();
            dh.close;
    
           var obj = highscores[name];
           if ( obj == null ) 
           {
                obj = new Object;
                obj.Points = 0;
           }
           if ( newhighscore > obj.Points )
           {
               obj.Points = newhighscore;
               obj.Time = newtime;
           }
           highscores[name] = obj;
     
           ...
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #8
    Regular Coder
    Join Date
    Jan 2013
    Location
    Germany
    Posts
    578
    Thanks
    4
    Thanked 77 Times in 77 Posts
    I don't know the project behind this, but if you're gonna use names as the primary key, you're likely to have a bad time pretty soon. Unless you can be 100% sure that names are unique, don't use them as if they were.

    Unfortunately, using something like an ID instead of the name would render Old Pedant's last, otherwise very true, point useless. But that's what indices in database systems are for.

  • #9
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,184
    Thanks
    10
    Thanked 569 Times in 550 Posts
    you might look into taffy DB if you want some query methods with that JSON.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/1/19) IE7:0.2, IE8:6.7, IE11:7.4, IE9:3.8, IE10:4.4, FF:18.3, CH:43.6, SF:7.8, MOBILE:27.5

  • #10
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,020
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    Quote Originally Posted by Airblader View Post
    I don't know the project behind this, but if you're gonna use names as the primary key, you're likely to have a bad time pretty soon. Unless you can be 100% sure that names are unique, don't use them as if they were.
    Since this is utterly and completely a toy system, I wasn't worried about a primary key, per se. I quote:
    A local storage would be a sufficient solution at the moment though.
    So with only local storage in play, the only way "Michael" can see changes made because of a new high score by "Marina" is to use the SAME MACHINE. None of the changes will ever be seen on any other machine, since he will not be using any server-side code.

    The whole thing can't be more than an exercise in learning some coding techniques, since it has no practical application that I can see.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #11
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,184
    Thanks
    10
    Thanked 569 Times in 550 Posts
    Quote Originally Posted by Old Pedant View Post
    So with only local storage in play, the only way "Michael" can see changes made because of a new high score by "Marina" is to use the SAME MACHINE. None of the changes will ever be seen on any other machine, since he will not be using any server-side code.

    The whole thing can't be more than an exercise in learning some coding techniques, since it has no practical application that I can see.
    minesweeper high scores have always been tied to that desktop machine and nobody ever really complained about it or saw it as a deal-breaker, same with the old mortal kombat 3 machine in the bar down the street that still has my high score...
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/1/19) IE7:0.2, IE8:6.7, IE11:7.4, IE9:3.8, IE10:4.4, FF:18.3, CH:43.6, SF:7.8, MOBILE:27.5

  • #12
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,020
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    Quote Originally Posted by rnd me View Post
    minesweeper high scores have always been tied to that desktop machine and nobody ever really complained about it or saw it as a deal-breaker, same with the old mortal kombat 3 machine in the bar down the street that still has my high score...
    WOW. Shows how much I play such games.

    I do play some games that keep track of high scores for all players, but only if you login and submit your score, which I never bother to do. So yes, in that case the highscores are only on my machine. But I always figured most serious players would *want* to submit their scores. Shows what I know.

    But all the more reason that I think using the name as the "primary key" (that is, here, as the key into the corresponding values) is perfectly adequate. On the one game that my wife and I both play on her pad, there's no confusion between "he" and "she". And I wouldn't expect any on a single machine.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #13
    Regular Coder
    Join Date
    Jan 2013
    Location
    Germany
    Posts
    578
    Thanks
    4
    Thanked 77 Times in 77 Posts
    @ Old Pedant

    I guess you're right -- a toy system with only local storage should be fine using the names as the PK.


  •  

    Tags for this Thread

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •