1. Hey! Guest! The 35th GMC Jam will take place between November 28th, 12:00 UTC - December 2nd, 12:00 UTC. Why not join in! Click here to find out more!
    Dismiss Notice

GMS 2 [SOLVED] JSON encoding with nested object inside an array

Discussion in 'Advanced Programming Discussion' started by bacteriaman, Nov 22, 2018.

  1. bacteriaman

    bacteriaman Member

    Joined:
    Jun 20, 2016
    Posts:
    23
    I'm trying to produce the following encoded JSON in order to POST scores to a RESTful service:

    Code:
    {
      "_links": {
        "type": {
          "href": "http://example.com"
        }
      },
      "title": {"value": "Score 100 by John"},
      "field_game_reference": [{"target_id": "2"}],
      "field_player_reference": [{"target_id": "3"}],
      "field_score_points": {"value": "100"}
    }
    
    I'm very close using the following DS functions:

    Code:
    var href = ds_map_create();
    ds_map_add(href, "href", "http://example.com");
    var type = ds_map_create();
    ds_map_add_map(type, "type", href);
    
    var map = ds_map_create();
    ds_map_add_map(map, "_links", type);
    
    var item = ds_map_create();
    ds_map_add(item, "value", "Score 100 by John");
    ds_map_add_map(map, "title", item);
    
    var item = ds_map_create();
    ds_map_add(item, "target_id", "2");
    ds_map_add_map(map, "field_game_reference", item);
    
    var item = ds_map_create();
    ds_map_add(item, "target_id", "3");
    ds_map_add_map(map, "field_player_reference", item);
    
    var item = ds_map_create();
    ds_map_add(item, "value", "100");
    ds_map_add_map(map, "field_score_points", item);
    
    ds_map_destroy(item);
    ds_map_destroy(href);
    ds_map_destroy(type);
    ds_map_destroy(map);
    
    This outputs the following:

    Code:
    {
      "field_player_reference": { "target_id": "3" },
      "_links": {
        "type": {
          "href": "http:\/\/example.com"
        }
      },
      "title": { "value": "Score 100 by John" },
      "field_game_reference": { "target_id": "2" },
      "field_score_points": { "value": "100" }
    }
    
    The only thing different is the array (square brackets) wrapping the object (curly brackets) for the two field references:

    Code:
      "field_game_reference": [{"target_id": "2"}],
      "field_player_reference": [{"target_id": "3"}],
    
    This presumably requires another type of nesting, but the syntax eludes me. Any advice is greatly appreciated.

    Note the above GML has not been optimized. Perhaps there's a more efficient way to go about it (?)
     
  2. Bart

    Bart Member

    Joined:
    Jun 21, 2016
    Posts:
    190
    Those square brackets in the JSON always correspond to a ds_list in GameMaker. To let it know that you added a ds_list as a ds_map_value, you can use ds_map_add_list. To indicate that a map was added to a list, you can use ds_list_mark_as_map.

    So, for example, for the field_game_reference, you should first add the ds_map item to a ds_list, then add that ds_list to map:
    Code:
    var item = ds_map_create();
    var list = ds_list_create();
    ds_map_add(item, "target_id", "2");
    ds_list_add(list, item);
    ds_list_mark_as_map(list, ds_list_size(list)-1);
    ds_map_add_list(map, "field_game_reference", list);
    Unfortunately, there's no more efficient way to do this at the moment, although chained accessors are on the roadmap.

    Also note that you don't have to destroy any of the additional ds_lists or ds_maps that you add using ds_list_mark_as_list, ds_list_mark_as_map, ds_map_add_list, ds_map_add_map. Just destroy the root map. In this case, that would be map.
     
    Last edited: Nov 22, 2018
    bacteriaman likes this.
  3. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    4,612
    The built-in functionality leaves a lot to be desired for, but I've written utilities making them a bit more bearable.

    For building nested JSON structures, see the JsonData, JsonList and JsonMap constructor scripts in my GMSugar library. The wiki there has examples of how to use them.

    For accessing nested JSON structures, see the Get and Set scripts from my Universal Accessor library. That's the best I've got until YoYo makes up its mind about chained accessors.
     
    bacteriaman likes this.
  4. bacteriaman

    bacteriaman Member

    Joined:
    Jun 20, 2016
    Posts:
    23
    @Bart, indeed, ds_list_mark_as_map did the trick--thank you! I ended up using "0" instead of ds_list_size for the second param. And thanks for the tip about the single ds_map_destroy.

    @FrostyCat, your JSON scripts sound super useful--thank you!
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice