dicksonlaw583 / jsontoolkit

Companion scripts for json_encode() and json_decode() (GMS 2.x)
9 stars 2 forks source link

Can't insert into plain Json list #8

Open Dan-D-Game-Dev opened 1 month ago

Dan-D-Game-Dev commented 1 month ago

Hello. I'm using this library to implement a save system in my game, and have some code which iterates through a series of structs/arrays and turns them into a JsonStruct. In that code, I need to be able to create a JsonStruct(JsonList)) and then start inserting the composite elements into it. However, the json_insert_nested library, contrary to documentation, does not allow providing two arguments, which is necessary as the path to insert at is top level.

I think the work-around I have to use for this is to ensure all lists are within a map and unroll my recursive logic to insert them into a list within a map, which is not ideal.

Here is the offending code

/// @description json_insert_nested(@jsonstruct, ..., jsonsubdata)
/// @param @jsonstruct
/// @param  ...
/// @param  jsonsubdata
if (argument_count < 3) {
    show_error("Expected at least 3 arguments, got " + string(argument_count) + ".", true);
}

The path parameter should be allowed to be passed as 0 arguments.

Alternatively, it would be really nice if one could construct JsonList and JsonMap elements from an existing list/map, instead of having to first create an empty one and then insert elements into it one by one.

Dan-D-Game-Dev commented 1 month ago

Edit: Realized I can just make the second argument "undefined" and that works. I don't feel it was super clear, but I see how the documentation implied that.

Dan-D-Game-Dev commented 1 month ago

Okay, so sorry, I do have a genuine issue with this library after some testing.

The following code, I've found, outputs 2

var _map = ds_map_create()
ds_map_add(_map, "k", "v")
if ds_exists(_map, ds_type_map) {
    if is_real(_map) {
        show_debug_message("1")
    } else {
        show_debug_message("2")
    }
}

That is to say, _map fails the is_real check

In your code for json_set, you have the following:

// Stop if _json_dig() errors out
var current = _json_dig(argument[0], path, 1);
if (path[0] <= 0) {
    return path[0];
}

then in _json_dig

// Check existence of top
if (_json_not_ds(current, ds_type_map)) {
    path[@ 0] = 0;
    return undefined;
}

then in _json_not_ds

return !(is_real(argument0) && ds_exists(argument0, argument1));

The code appears to error out if arg0, which is a ds_map, is not a real. Why is this code here? I feel like this makes the library unusable for encoding data, doesn't it? It always assumes the ds_maps produced by the library are not ds_maps and fails to set the data. Am I missing something?

Dan-D-Game-Dev commented 1 month ago

Confirmed by manually editing the extension file that removing the is_real(argument0) check fixes the library and it works as intended. Maybe they changed is_real at some point and it broke?

dicksonlaw583 commented 1 month ago

You shouldn't use this library for new code based on arrays and structs. Converting to DS data structures for JSON has been obsolete since GMS 2.3.2. I should have sunsetted this library years ago.

Starting in 2022.6, DS data structure IDs changed from being simple numbers to being its own "ref" type, so that is_real check stopped working past that point.

Dan-D-Game-Dev commented 3 weeks ago

Thanks. Got referred to this from some old forum posts. Appreciate the help.