• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

HTML5 json to dsmap - I need help

J

jaber

Guest
Hi;
I am creating my own leaderboard and for hat I have created an API in AWS and I have tested from Gamemaker and I see its working fine.
in create event

GML:
r_json = "null";
r_map = "null";
r_car = "null";

url = "https://xxxxx2.amazonaws.com/default/Query_lambda?playerid=jaber31";
get = http_get(url);
in Async-HTTP

Code:
if ds_map_find_value(async_load, "id") == get
   {
   if ds_map_find_value(async_load, "status") == 0
      {
      r_json= ds_map_find_value(async_load, "result");
      r_map = json_decode(r_json);
      r_car = r_map [? "Player_car"]
  }
   else
      {
      r_json = "empty returned";
      }
   }
in draw
Code:
draw_text(10,100,r_json);
I get this result
{"statusCode": 200, "body": {"Player_car": "Buggati", "Player_name": "Jaber", "Update_date": "2020-10-31--05:49:33", "Player_KM": "1000", "Player_level": "Beginner", "Player_ID": "jaber31", "Player_score": 309.0}}

Sofar so good.... now to the problem.. when I draw the value of r_car I still get null! I guess I am missing something here : /
the question is, how can I convert json to dsmap correctly?

by the way, I followed the video of Heartbeast here but it looks like the API was used returned json without the prefix {"statusCode": 200, "body":
any workaround?
thanks
J
 

FrostyCat

Redemption Seeker
You don't have Player_car at the top level of that map, you only have statusCode and body. Always suit JSON code to the structure of the JSON data you get, DO NOT just copy it from unrelated contexts.
GML:
r_car = r_map[? "body"][? "Player_car"];
There is nothing confusing about JSON once you start looking at one depth at a time. Start at the highest depth and collapse everything deeper (i.e. any nested [] or {} structures). Iteratively find out where your target is in the current depth, bubble down, and repeat until you reach it.
 
J

jaber

Guest
You don't have Player_car at the top level of that map, you only have statusCode and body. Always suit JSON code to the structure of the JSON data you get, DO NOT just copy it from unrelated contexts.
GML:
r_car = r_map[? "body"][? "Player_car"];
There is nothing confusing about JSON once you start looking at one depth at a time. Start at the highest depth and collapse everything deeper (i.e. any nested [] or {} structures). Iteratively find out where your target is in the current depth, bubble down, and repeat until you reach it.
thanks very much for the help... and the explaination.. I appreciate it.

I used your code:
r_car = r_map[? "body"][? "Player_car"];

Gamemaker throwed an error
1604157818364.png
looks like an error because he did not like the syntax!
However, I modified to the following
GML:
r_body = r_map[? "body"];
r_car = r_body [? "Player_car"];
and it worked like a charm
thnx again
 

FrostyCat

Redemption Seeker
This is the reason you should always post the version you're using when asking for help with code. The syntax I provided is available on GMS 2.3+ only.
 
J

jaber

Guest
Apology to bring this up again, but this new scenario is more complicated and I can not figure it out

I am returning the top10 players in an array of json objects (that contains Player_ID and Player_score score for each) ; sofar after I got my json variable intialized
GML:
r_json= ds_map_find_value(async_load, "result");
the result looks like this

[{"Player_ID": "Mary", "Player_score": 78604.0}, {"Player_ID": "jaber_aus", "Player_score": 9524.0}, {"Player_ID": "Bismil", "Player_score": 8714.0}, {"Player_ID": "Sarah", "Player_score": 5289.0}, {"Player_ID": "Han", "Player_score": 871.0}, {"Player_ID": "awesome", "Player_score": 802.0}, {"Player_ID": "Lowe", "Player_score": 786.0}, {"Player_ID": "Edison", "Player_score": 100.0}, {"Player_ID": "sbm31", "Player_score": 98.0}, {"Player_ID": "Tesla", "Player_score": 98.0}]

I am confused since this is an array, i dont know if it is valid to use dsmap straight again?
Code:
r_map = json_decode(r_json);
or dsmap would not handle that?

what/how would be the easiest way to transfer this array to something feasible in gamemaker?
Thanks
J
 

rytan451

Member
GML:
var r_json = ds_map_find_value(async_load, "result");
var r_map_json = "{\"result\": " + r_json + "}";
var r_map = json_decode(r_json);
var r_list = r_map[? "result"];
Now, r_list should hold a valid list of player data, assuming that your json input was valid.
 

FrostyCat

Redemption Seeker
The Manual entry for json_decode clearly states what you should do in this situation:
The Manual said:
If the JSON to be decoded requires a hierarchy of lists and maps within the central ds_map, these are decoded too and also created for you, using the following rules (note that these rules apply to the top-level structure only):
  • Json is a single value - returns a ds_map with a single entry "default" that is the value

  • Json is an array of objects or values - returns a ds_map with a single entry "default" that is a ds_list of the objects or values

  • Json is an object - returns a ds_map that has the object entries in it
NOTE: When decoding arrays, there is a map with the key "default" ONLY when an array is the top level structure, and ONLY for that top-level array. Internal lists decode directly to ds_lists without being enclosed in a ds_map.
GML:
r_map = json_decode(r_json);
r_list = r_map[? "default"];
 
J

jaber

Guest
GML:
var r_json = ds_map_find_value(async_load, "result");
var r_map_json = "{\"result\": " + r_json + "}";
var r_map = json_decode(r_json);
var r_list = r_map[? "result"];
Now, r_list should hold a valid list of player data, assuming that your json input was valid.

thanks rytan,

I tried and unfortunately something is still going wrong.. and before I judge I wanted to ask you, is this code compatible with Gamemaker v2.2.5 or its 2.3?

another thing, I think there is a typo you made in your code... i think you mentioned mistakingly

var r_map = json_decode(r_json);

but you meant

var r_map = json_decode(r_map_json);

am I correct?

in any way, here is how the debug look
GML:
r_json= ds_map_find_value(async_load, "result");
       show_debug_message("r_json");
       show_debug_message(r_json);
      
       r_map_json = "{\"result\": " + r_json + "}";
       show_debug_message("r_map_json");
       show_debug_message(r_map_json);
      
       r_map = json_decode(r_map_json );
       show_debug_message("r_map");
       show_debug_message(r_map);
      
       r_list = r_map[? "result"];
       show_debug_message("r_list");
       show_debug_message(r_list);
      
       show_debug_message(r_list [? "Player_ID"]);
the result in browser is shown as below
1604341813507.png
 
J

jaber

Guest
The Manual entry for json_decode clearly states what you should do in this situation:

GML:
r_map = json_decode(r_json);
r_list = r_map[? "default"];
thanks Frosty
I just wished the documentation had explained things more clearly and plus some step by step example... however this is not my point now.

i tried your code and I still can not figure out how to get to the record Player_ID and Player_score
Code:
 r_json= ds_map_find_value(async_load, "result");
       show_debug_message("r_json");
       show_debug_message(r_json);
      
       r_map = json_decode(r_json);
       show_debug_message("r_map");
       show_debug_message(r_map);
      
      
       r_list = r_map[? "default"];
       show_debug_message("r_list");
       show_debug_message(r_list);
  
       Player = r_list [? "Player_score"]
       show_debug_message(Player);
this is the output
1604342307935.png

any further help would be much appreciated
J
 

FrostyCat

Redemption Seeker
This is easy if you use map accessors only with maps, and list accessors only with lists.
GML:
r_map = json_decode(r_json);
r_list = r_map[? "default"];
r_player = r_list[| 0];
r_name = r_player[? "Player_ID"];
r_score = r_player[? "Player_score"];
Read up on how to read the addressing path in a JSON structure. For example, the path to the first player's name is "default" > 0 > "Player_ID".
 
J

jaber

Guest
This is easy if you use map accessors only with maps, and list accessors only with lists.
GML:
r_map = json_decode(r_json);
r_list = r_map[? "default"];
r_player = r_list[| 0];
r_name = r_player[? "Player_ID"];
r_score = r_player[? "Player_score"];
Read up on how to read the addressing path in a JSON structure. For example, the path to the first player's name is "default" > 0 > "Player_ID".
very much appreciated Frosty.. your solution is valid.. and thanks for the advice.. i will defenitly read your recommendations
 
Top