clugg / sm-json

A pure SourcePawn JSON encoder/decoder.
GNU General Public License v3.0
82 stars 8 forks source link

Added ability to rename key-values. #21

Closed alexevladgabriel closed 2 years ago

alexevladgabriel commented 3 years ago

Added a new function to rename key-values of JSON Objects. I had needed that feature in one plugin rewrite. If you have any ideas for modification and making test cases.

MAGNAT2645 commented 3 years ago

You could do it like this:

  1. Use switch, it should be faster in such cases.
  2. You don't need to use reference for obj because you're not modifying it (only its data).
  3. Since key and toKey aren't modified in your function, mark them as const.
  4. You should remove key once after setting new key (less code).
  5. Added comparison check for key and toKey (unneccessary).
stock bool json_rename(JSON_Object obj, const char[] key, const char[] toKey) {
    JSONCellType type = obj.GetKeyType( key );
    if ( type == JSON_Type_Invalid ) return false;
    if ( StrEqual( key, toKey, true ) ) return false;

    switch ( type ) {
        case JSON_Type_String: {
            int length = obj.GetKeyLength( key ) + 1;
            char[] value = new char[length];
            obj.GetString( key, value, length );
            obj.SetString( toKey, value );
        }
        case JSON_Type_Int:    obj.SetInt( toKey, obj.GetInt( key ) );
        case JSON_Type_Float:  obj.SetFloat( toKey, obj.GetFloat( key ) );
        case JSON_Type_Bool:   obj.SetBool( toKey, obj.GetBool( key ) );
        case JSON_Type_Object: obj.SetObject( toKey, obj.GetObject( key ) );
    }

    obj.Remove( key );
    return true;
}

And since json_rename returns bool, JSON_Object.Rename should return it too. public bool Rename(const char[] key, const char[] toKey)

MAGNAT2645 commented 3 years ago

Oh, you can also move JSON_Type_Invalid under switch. So the whole construction could look like this:

    switch ( obj.GetKeyType( key ) ) {
        case JSON_Type_Invalid: return false;
        case JSON_Type_String: {
            int length = obj.GetKeyLength( key ) + 1;
            char[] value = new char[length];
            obj.GetString( key, value, length );
            obj.SetString( toKey, value );
        }
        case JSON_Type_Int:    obj.SetInt( toKey, obj.GetInt( key ) );
        case JSON_Type_Float:  obj.SetFloat( toKey, obj.GetFloat( key ) );
        case JSON_Type_Bool:   obj.SetBool( toKey, obj.GetBool( key ) );
        case JSON_Type_Object: obj.SetObject( toKey, obj.GetObject( key ) );
    }
clugg commented 3 years ago

Thanks very much @alexevladgabriel for the suggestion/implementation and @MAGNAT2645 for reviewing it! I'm in the midst of working on some underlying changes (a new major release) so I am going to hold off on merging this for the time being, but I will update you here once it's released.

clugg commented 2 years ago

This has been released under v3.3.0. Thanks for your contribution! :)