Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
LuaJIT and Json: Error reading 'null' — Gideros Forum

LuaJIT and Json: Error reading 'null'

HubertRonaldHubertRonald Member
edited March 2014 in Bugs and issues
Hi folks,
I'm having a problem with LuaJIT and Json
I get the next error and the project can't launch it:

Library/json.lua:325: Error reading 'null': {"data":{"sets": ...(more details)... ,[0,0,0],[0,0,
the print is incomplete so this shows me the system

This is a piece of code where the error occurs
function JsonReader:TestReservedWord(t)      --line 322
	for i, v in ipairs(t) do                              --line 323
		if self:Next() ~= v then                   --line 324
			 error(string.format(               --line 325
				"Error reading '%s': %s",  --line 326
				table.concat(t),               --line 327
				self:All()))
		end
	end
end
It was working well until the level is finished, and then used dataSaver.saveValue("sets", sets) for save scores, coins, and so.

I don't know if somebody have or had the same problem or if have some idea about this issue.
Any help thanks

P.S.
Without LuaJIT, Json worked fine in my project and saved all information.

Comments

  • ar2rsawseenar2rsawseen Maintainer
    @HubertRonald interesting
    I have not tried lua json with the luajit, been using native json available with Gideros and it all seems to run great :)

    Unfortunately as lua json is not our lib, I doubt I can undestand the specific to fix it, would really recommend to move to native json
  • Thanks @ar2rsawseen for your answer

    I just fix this some minutes before. I remembered your suggestion in this forum http://giderosmobile.com/forum/discussion/4673/luajit-and-tntparticlesengine#Item_6

    So I did the next (this is only a little piece of my code)

    1.-First step
    sets = nil
    if  (not sets) then
    	sets = {...} -- before sets ={}
            for i=1, 6 do
                  sets.myScore[i]={...} -- before   sets.myScore[i]={...}
                  for i=1,16 do
                       sets.myScore[i][j] = 0
                  end
             end
    end
    2.- Second step
    save all proyect and exit gideros

    3.- Third Step
    restart machine and launch gideros

    4.- :D

    @ar2rsawseen with respect to a native LuaJit,I had no knowledge about it, if you were friendly you could tell me where I can get it and some link or example of how this works.

    thanks again :)>-

    P.S.
    5.- Fifth Step
       --sets = nil remove this line
  • ar2rsawseenar2rsawseen Maintainer
    edited March 2014 Accepted Answer
    @HubertRonald if you are using latest Gideros version, then basically:
    require "json"
    local t= {}
    local str = json.encode(t)
    t = json.decode(str)
    http://docs.giderosmobile.com/reference/plugin/json#json

    Likes: HubertRonald

    +1 -1 (+1 / -0 )Share on Facebook
  • Ok @ar2rsawseen I going to try this, and anything I do not understand will ask
  • Hi @ar2rsawseen.

    I read the reference manual and I tried to use the lines above provided by you, but I think it is not enough for me because I'm not understanding the mechanics of native Json well.
    require "json"
     
    if not t then
    	t={}
    	t.myCoins= 0
    	t.worldScore={}
    	for i =1, 3 do
    		t.worldScore[i]=0
    	end
    	str = json.encode(t)
    	t = json.decode(str)
    end
     
    print("coins:",t.myCoins,"score world 2",t.worldScore[2])
     
    t.myCoins= t.myCoins+100
    str = json.encode(t)
    t = json.decode(str)
    When running the code each time I press the play button on the Gideros Player, should work up the amount of coins you have, but this is not happening.

    Other question I have is regarding the *. json How does it works? if I have the following file: worlds.json
    {"world":[
    {"name":"world 1","levels":5},
    {"name":"world 2","levels":5},
    {"name":"world 3","levels":5}
    ]}
    -- maybe:
    myWorlds=json.decode("./worlds")
    Please, an example where you can see how the native json works would be very useful for me.

    Thanks again
  • @ar2rsawseen I found this link yours

    http://www.gamasutra.com/blogs/ArtursSosins/20131129/205956/Learning_Gideros_in_10_easy_steps.php

    And Step 10 answered my first question (coins grow)
    t = getData("t")
     
    if not t then
    	t={}
    	t.myCoins= 0
    	t.worldScore={}
    	for i =1, 3 do
    		t.worldScore[i]=0
    	end
    	saveData("t", t)
    end
     
    print("coins:",t.myCoins,"score world 2",t.worldScore[2])
    t.myCoins= t.myCoins+100
    saveData("t", t)
    But still I haven't any idea regarding the *. json How does it works? if I have the following file: worlds.json (I listed above)
    {"world":[
    {"name":"world 1","levels":5},
    {"name":"world 2","levels":5},
    {"name":"world 3","levels":5}
    ]}
    I've see the next file (than is yours)
    https://github.com/gideros/KitchenSink/blob/master/examples/Native_Json/Native_Json.lua

    And I tried this but without successful :-/ :-/ :-/ :-/
    myWorlds = load("worlds.json")
    print(type(myWorlds)) -- I got "nil"
    This is for levels packs as you know well.
    Thanks again
  • SinisterSoftSinisterSoft Maintainer
    edited March 2014
    I know it' not to do with the actual post - but I think you should base you coin grow on time past - including time past whilst not playing the game (maybe at a reduced rate). This is what a lot of games do now that use coins/lives as a way of getting players addicted.
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • ar2rsawseenar2rsawseen Maintainer
    @HubertRonald json only serializes table or any value to string and deserializes it back to the values
    As you have figured it out, you also need a mechanism to save and read the persistent data.

    For that I have created a module dataSaver, which now uses native json:

    https://github.com/ar2rsawseen/dataSaver

    More on its usage:
    http://appcodingeasy.com/Gideros-Mobile/Save-and-load-data-module-for-Gideros-Mobile

    But basically, you need to note, that you can only save/write files in documents directory, so filenames should have |D| before them :)
  • @ar2rsawseen Tried last post but I got the next bug
    dataSaver.lua:27: Cannot serialise number: must not be NaN or Inf
    stack traceback:
    	Library/dataSaver.lua:27: in function 'saveValue'
    Here a summary code modified
    sets = dataSaver.loadValue("|D|sets")
     
    if not sets then
    	sets={}
    	sets.myCoins= 0
    	sets.worldScore={}
    	for i =1, 3 do
    		sets.worldScore[i]=0
    	end
    	dataSaver.saveValue("|D|sets", sets)
    end
     
    print("coins:",sets.myCoins,"score world 2",sets.worldScore[2])
    sets.myCoins= sets.myCoins+100
    dataSaver.saveValue("|D|sets", sets)
    Apparently the table "sets" are not creating and so loaded as empty, but the error does not occur when the app starts, but when to navigate the app, you execute an action that may lead to keep the same information twice for example, you play the level twice, you turn off the music for the second time, ie there is something going on and that did not happen when the luaJit was not used.

    Another view of where the information is stored, ie tables and if one can be edited with NotePad + + or TextWargler

    Maybe at some point I saved "sets = nil" to clear all the information, but delimiting again I created the table "sets" and kept all the information and as I say this worked for me, and of course at that time used the json.lua
    but I had not enabled luaJit

    Thanks again
  • Hi @SinisterSoft
    Thanks for your answer I will take into account
  • ar2rsawseenar2rsawseen Maintainer
    @HubertRonald interesting, but you can also try print_r the structure to see its contents:
    http://giderosmobile.com/forum/discussion/comment/20510#Comment_20510

    Also can you try it this way:
    sets = dataSaver.load("|D|sets")
     
    if not sets then
    	sets={}
    	sets.myCoins= 0
    	sets.worldScore={}
    	for i =1, 3 do
    		sets.worldScore[i]=0
    	end
    	dataSaver.save("|D|sets", sets)
    end
     
    print("coins:",sets.myCoins,"score world 2",sets.worldScore[2])
    sets.myCoins= sets.myCoins+100
    dataSaver.save("|D|sets", sets)
    As
    saveValue
    saves key/value to a shared file, while
    save
    creates its own separate file, and maybe you already had something bad in the shared file
  • Hi @ar2rsawseen nice script
     print_r()
    is very useful :)>-

    Now I know that "sets" table is created with all its information.
    I changed my code and update all classes
    --[[ 
    change: dataSaver.loadValue("|D|sets") by: dataSaver.load("|D|sets")
    change: dataSaver.saveValue("|D|sets") by: dataSaver.save("|D|sets")
    ]]
    I get the next error (but the project can be re-launched):
    dataSaver.lua:73: Cannot serialise number: must not be NaN or Inf
    stack traceback:
    This is the line where the error occurs :-? :-? :-? :-?
    dataSaver.lua:73: Cannot serialise number: must not be NaN or Inf
    stack traceback:
    	./Library/dataSaver.lua:73: in function 'save'
    So take than I said and modified the first paragraph:

    " the table "sets" is create, but the error does not occur when the app starts, but when to navigate the app, you execute an action that may lead to keep the same information twice for example, you play the level twice, you turn off the music for the second time, ie there is something going on and that did not happen when the luaJit was not used."

    Any suggestion is welcome
  • I forgotten, the table of "sets" never is saved and when you launch of app, table of "sets" is created again.
  • Hi folks again,
    I think why this is failing
    json.lua:325: Error reading 'null': -- not native json
    dataSaver.lua:27: Cannot serialise number: must not be NaN or Inf
    dataSaver.lua:73: Cannot serialise number: must not be NaN or Inf
    a little code:
    myMath = dataSaver.load("|D|myMath")
     
    if not myMath then
    	myMath={}
    	myMath.NaN = 0/0         -- case 1
    	--myMath.Inf = 1/0       -- case 2
     
    	dataSaver.save("|D|myMath", myMath)
    end
    The difference is that json.lua shows you on the screen where Gideros Player Inf or NaN is generated, but when you leave this and go back to running the model fails, then simply suppress myMath = dataSaver.load("|DmyMath") to re-run the model.

    While the native json does not show you where the error actually occurs within the model (this is critical for debugging) but unlike json.lua, you don't need delete myMath = dataSaver.load("|D|myMath") for re-run the model.

    I will continue doing more testing and comment anything on this line

    Finally, any suggestion is welcome

    P.S
    For more detail see
    http://lua-users.org/wiki/InfAndNanComparisons
  • ar2rsawseenar2rsawseen Maintainer
    Ah I see, @HubertRonald so json.lua actually saved it, and native json could not read it?
  • @ar2rsawseen are right

    But json.lua indicate in which variable is produced Nan or Inf (but not in which line of code)
    {"data":{"sets": ...(more details)... ,[0,0,0],[0,0,
    the next variable was NaN or Inf therefore the table is cut in this point.

    However the native json no traces of like knowing that variable was NaN or Inf, it can be a headache when you are debugging.

    My suggestion
    -------------
    if native json can't show you than variable is Inf or NaN, create your project with json.lua and when you are sure than variables aren't Inf or NaN and when you are ready for launch your application, you CHANGE json.lua for NATIVE.

    Because it would be terrible or catastrophic :-t save the table is cut, then it would have to relaunch the application variables to zero, and this would generate a tremendous disappointment for users X( X( X( X( because they would lose their scores, so on.
  • I forgot, I don't know if you lose some information when a variable was NaN or Inf with json native and try save.
Sign In or Register to comment.