// vim: set ts=4 sw=4 tw=99 noet: // // AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). // Copyright (C) The AMX Mod X Development Team. // // This software is licensed under the GNU General Public License, version 3 or higher. // Additional exceptions apply. For full license details, see LICENSE.txt or visit: // https://alliedmods.net/amxmodx-license #include #include //For encoding new buffer[500]; public plugin_init() { register_plugin("JSON Test", "1.0", "Ni3znajomy"); register_srvcmd("json_test_encode", "cmdJSONTestEncode"); register_srvcmd("json_test_decode", "cmdJSONTestDecode"); register_srvcmd("json_test_replace", "cmdJSONTestReplace"); register_srvcmd("json_test_validate", "cmdJSONTestValidate"); register_srvcmd("json_test_has_key", "cmdJSONTestHasKey"); register_srvcmd("json_test_remove", "cmdJSONTestRemove"); } public cmdJSONTestEncode() { if (read_argc() < 3) { server_print("Usage: json_test_encode "); return; } // Use init funcs? new bool:init = bool:read_argv_int(1); //Pretty new bool:pretty = bool:read_argv_int(2); // Create root array new JSON:root_array = json_init_array(); // Init & setup object new JSON:object = json_init_object(); if (!init) { json_object_set_string(object, "string", "https://alliedmods.net"); json_object_set_number(object, "number", 45); json_object_set_real(object, "real", -5.31); json_object_set_null(object, "null.null"); json_object_set_bool(object, "bool.true", true, true); } else { ObjectSetKey(object, "string", json_init_string("https://alliedmods.net")); ObjectSetKey(object, "number", json_init_number(45)); ObjectSetKey(object, "real", json_init_real(-5.31)); ObjectSetKey(object, "null.null", json_init_null()); ObjectSetKey(object, "bool.true", json_init_bool(true), true); } // Add object to root array ArrayAppendValue(root_array, object); new JSON:parent = json_get_parent(root_array); if (parent != Invalid_JSON) { server_print("Root array has parent!"); json_free(parent); json_free(root_array); return; } // Append some values to root array if (!init) { json_array_append_real(root_array, -31.1); json_array_append_number(root_array, -42); json_array_append_bool(root_array, false); json_array_append_null(root_array); } else { ArrayAppendValue(root_array, json_init_real(-31.1)); ArrayAppendValue(root_array, json_init_number(-42)); ArrayAppendValue(root_array, json_init_bool(false)); ArrayAppendValue(root_array, json_init_null()); } // Serialiaze to file and to buffer json_serial_to_file(root_array, "json_encode_test_to_file.txt", pretty); json_serial_to_string(root_array, buffer, charsmax(buffer), pretty); // Put buffer's content to file new file = fopen("json_encode_test_to_string.txt", "wt"); if (!file) { server_print("Couldn't create file"); return; } fputs(file, buffer); fclose(file); server_print("Encoding done (%d bytes)", json_serial_size(root_array, pretty)); json_free(root_array); } public cmdJSONTestDecode() { // Check if encode command was run if (!strlen(buffer)) { server_print("Run ^"json_test_encode^" first!"); return; } new JSON:root_array = json_parse(buffer); new JSON:for_compare = json_parse("json_encode_test_to_file.txt", true); // Check if they are the same if (root_array != for_compare || !json_is_array(root_array)) { if (root_array != Invalid_JSON) json_free(root_array); if (for_compare != Invalid_JSON) json_free(for_compare); server_print("Root value is not array!"); return; } // We don't need this anymore json_free(for_compare); DecodeArray(root_array); json_free(root_array); } //Creating inversed root array public cmdJSONTestReplace() { // Check if encode command was run if (!strlen(buffer)) { server_print("Run ^"json_test_encode^" first!"); return; } new JSON:root_array_orig = json_parse(buffer); new JSON:root_array_copy = json_deep_copy(root_array_orig); json_free(root_array_orig); //Replace null with object new JSON:object = json_array_get_value(root_array_copy, 0); json_array_replace_value(root_array_copy, 4, object); json_free(object); //Replace object with null json_array_replace_null(root_array_copy, 0); //Replace bool with real and vice versa new Float:realnum = json_array_get_real(root_array_copy, 1); new bool:boolval = json_array_get_bool(root_array_copy, 3); json_array_replace_real(root_array_copy, 3, realnum); json_array_replace_bool(root_array_copy, 1, boolval); //Replace number with random json_array_replace_number(root_array_copy, 2, random(42)); json_serial_to_file(root_array_copy, "json_replace_test.txt", true); json_free(root_array_copy); server_print("Values replaced!"); } public cmdJSONTestValidate() { // Check if encode command was run if (!strlen(buffer)) { server_print("Run ^"json_test_encode^" first!"); return; } if (read_argc() < 2) { server_print("Usage: json_test_validate "); return; } //Should validating be succeed? new bool:success = bool:read_argv_int(1); //Create schema new JSON:schema = json_init_object(); if (success) json_object_set_string(schema, "string", ""); else json_object_set_real(schema, "string", 0.0); json_object_set_number(schema, "number", 0); json_object_set_null(schema, "real"); //Null validate all types new JSON:root_array = json_parse(buffer); //Get root array new JSON:object = json_array_get_value(root_array, 0); //Get object from it new bool:result = json_validate(schema, object); //Validate object with our schema server_print("Validate %d! (result: %d)", result, result == success); json_free(object); json_free(schema); json_free(root_array); } public cmdJSONTestHasKey() { // Check if encode command was run if (!strlen(buffer)) { server_print("Run ^"json_test_encode^" first!"); return; } if (read_argc() < 2) { server_print("Usage: json_test_has_key "); server_print("Available types:^nn - null^ns - string^nr - number^no - object^na - array^nb - boolean"); return; } //Get root array new JSON:root_array = json_parse(buffer); new JSON:object = json_array_get_value(root_array, 0); //Get object new keyname[32], type[10]; new JSONType:jtype = JSONError; read_argv(1, keyname, charsmax(keyname)); //Key name that have to be found new bool:dotnot = bool:read_argv_int(2); //Use dot natation? (optional) read_argv(3, type, charsmax(type)); //Type of searched value (optional) //Get type switch(type[0]) { case 'n': jtype = JSONNull; case 's': jtype = JSONString; case 'r': jtype = JSONNumber; case 'o': jtype = JSONObject; case 'a': jtype = JSONArray; case 'b': jtype = JSONBoolean; } new bool:found = json_object_has_value(object, keyname, jtype, dotnot); if (jtype == JSONError) server_print("Key %s%s!%s Found!", keyname, (dotnot) ? " using dotnot" : "", (found) ? "" : " Not"); else { GetTypeName(jtype, type, charsmax(type)); //Get type as string server_print("Key %s (type: %s)%s!%s Found!", keyname, type, (dotnot) ? " using dotnot" : "", (found) ? "" : " Not"); } json_free(object); json_free(root_array); } public cmdJSONTestRemove() { // Check if encode command was run if (!strlen(buffer)) { server_print("Run ^"json_test_encode^" first!"); return; } if (read_argc() < 3) { server_print("Usage: json_test_has_key "); server_print("Available types:^na - array^no - object"); return; } //Get root array new JSON:root_array = json_parse(buffer); new type[10], bool:is_object, bool:success; read_argv(1, type, charsmax(type)); //Type is_object = type[0] == 'o'; //Is type object? if (!is_object && type[0] != 'a') //If not, is it array? { server_print("Unknown type: %c", type[0]); //Fail, unknown type return; } if (is_object) { new keyname[32]; new JSON:object = json_array_get_value(root_array, 0); read_argv(2, keyname, charsmax(keyname)); //Key to delete or "clear" if object have to be cleared new bool:dotnot = bool:read_argv_int(3); //Use dot notation? if (equal(keyname, "clear")) success = json_object_clear(object); else success = json_object_remove(object, keyname, dotnot); json_free(object); } else { new index = read_argv_int(2); //Entry to delete or -1 if array have to be cleared if (index == -1) success = json_array_clear(root_array); else success = json_array_remove(root_array, index); } //Dump result json_serial_to_file(root_array, "json_remove_test.txt", true); //Use pretty format for better view json_free(root_array); server_print("Removing %s! (Results dumped)", (success) ? "succeed" : "failed"); } ObjectSetKey(JSON:object, const key[], JSON:node, bool:dot_not = false) { json_object_set_value(object, key, node, dot_not); json_free(node); } ArrayAppendValue(JSON:array, JSON:node) { json_array_append_value(array, node); json_free(node); } DecodeArray(&JSON:array) { //for storing string data new tempbuf[2][100]; new JSON:array_value, JSON:parent_value; for (new i = 0; i < json_array_get_count(array); i++) { array_value = json_array_get_value(array, i); parent_value = json_get_parent(array_value); if (parent_value != array) { json_free(parent_value); json_free(array_value); server_print("[Array] Parent value differs!"); break; } json_free(parent_value); switch (json_get_type(array_value)) { case JSONNull: server_print("Array Index %d (Null)", i); case JSONString: { json_get_string(array_value, tempbuf[0], charsmax(tempbuf[])); json_array_get_string(array, i, tempbuf[1], charsmax(tempbuf[])); server_print("Array Index %d (String) value: %s | index: %s", i, tempbuf[0], tempbuf[1]); } case JSONNumber: { new num1 = json_get_number(array_value), num2 = json_array_get_number(array, i); new Float:num3 = json_get_real(array_value), Float:num4 = json_array_get_real(array, i); server_print("Array Index %d (Number/Real) value: %d/%f | index: %d/%f", i, num1, num3, num2, num4); } case JSONObject: { new iCount = json_object_get_count(array_value); server_print("Array Index %d (Object) %d elements", i, iCount); DecodeObject(array_value); } case JSONArray: { new iCount = json_array_get_count(array_value); server_print("Array Index %d (Array) %d elements", i, iCount); DecodeArray(array_value); } case JSONBoolean: { new bool:val1 = json_get_bool(array_value), bool:val2 = json_array_get_bool(array, i); server_print("Array Index %d (Bool) value %d | index %d", i, val1, val2); } } json_free(array_value); } } DecodeObject(&JSON:object) { //for storing string data new tempbuf[2][100]; new key[30]; new JSON:obj_value, JSON:parent_value; for (new i = 0; i < json_object_get_count(object); i++) { json_object_get_name(object, i, key, charsmax(key)); obj_value = json_object_get_value_at(object, i); parent_value = json_get_parent(obj_value); if (parent_value != object) { json_free(parent_value); json_free(obj_value); server_print("[Object] Parent value differs!"); break; } json_free(parent_value); switch (json_get_type(obj_value)) { case JSONNull: server_print(" Object Key ^"%s^" (Null)", key); case JSONString: { json_get_string(obj_value, tempbuf[0], charsmax(tempbuf[])); json_object_get_string(object, key, tempbuf[1], charsmax(tempbuf[])); server_print(" Object Key ^"%s^" (String) value: %s | key: %s", key, tempbuf[0], tempbuf[1]); } case JSONNumber: { new num1 = json_get_number(obj_value), num2 = json_object_get_number(object, key); new Float:num3 = json_get_real(obj_value), Float:num4 = json_object_get_real(object, key); server_print(" Object Key ^"%s^" (Number/Real) value: %d/%f | key: %d/%f", key, num1, num3, num2, num4); } case JSONObject: { new iCount = json_object_get_count(obj_value); server_print(" Object Key ^"%s^" (Object) %d elements", key, iCount); //Let's get its value by dot notation if (equal(key, "bool")) { //dotnot new bool:val1 = json_object_get_bool(object, "bool.true", true); new bool:val2 = json_object_get_bool(obj_value, "true"); json_object_get_name(obj_value, 0, key, charsmax(key)); server_print(" Object Key ^"%s^" (Bool) dot %d | nodot: %d", key, val1, val2); } else DecodeObject(obj_value); } case JSONArray: { new iCount = json_array_get_count(obj_value); server_print(" Object Key ^"%s^" (Array) %d elements", key, iCount); DecodeArray(obj_value); } case JSONBoolean: { new bool:val1 = json_get_bool(obj_value), bool:val2 = json_object_get_bool(object, key); server_print(" Object Key ^"%s^" (Bool) value %d | index %d", key, val1, val2); } } json_free(obj_value); } } GetTypeName(JSONType:type, buffer[], maxlen) { switch(type) { case JSONNull: copy(buffer, maxlen, "Null"); case JSONString: copy(buffer, maxlen, "String"); case JSONNumber: copy(buffer, maxlen, "Number"); case JSONObject: copy(buffer, maxlen, "Object"); case JSONArray: copy(buffer, maxlen, "Array"); case JSONBoolean: copy(buffer, maxlen, "Boolean"); } }