This extension wraps Jansson, a C library for encoding, decoding and manipulating JSON data. Jansson is licensed under the MIT license.
As this is based off the 2.3.1 sources currently, I cherry picked some of the younger commits to allow building on windows.
The original sources can be found here.
I've adapted parts of the original documentation for the pawn language and recommend referring to smjansson.inc for SourceMod specific details. Still pretty much of it is copy'n'pasted.
Thanks to akheron for providing such detailed documentation and a nice library in the first place.
The source code is hosted on github.
Changelog can be found here.
Latest binaries here.
By using reference stealing methods.
These methods automatically close the Handle of the value-object you are setting/adding/inserting, making your code much cleaner.
// Create a new JSON object new Handle:hObj = json_object();
// Create new JSON strings/integer and 'set' them on the JSON object // Hint: We don't need to close the handles of the values we push, // because we are using the reference stealing method // json_object_set_new() json_object_set_new(hObj, "jsonrpc", json_string("2.0")); json_object_set_new(hObj, "method", json_string("subtract")); json_object_set_new(hObj, "id", json_integer(1));
// Create a new JSON array and add the two integers to it. // Again, we don't need to close the hArray Handle, because we've // pushed it to the object by reference stealing. // This also means that the hArray handle won't be valid anymore // afterwards. new Handle:hArray = json_array(); json_array_append_new(hArray, json_integer(42)); json_array_append_new(hArray, json_integer(23)); json_object_set_new(hObj, "params", hArray);
// And finally transform the JSON object to a JSON string new String:sJSON[4096]; json_dump(hObj, sJSON, sizeof(sJSON));
// And output it. LogMessage("Created JSON is:\n%s\n", sJSON);
// Close the Handle to the JSON object, i.e. free it's memory // and free the Handle. CloseHandle(hObj); }
This is a lossy conversion as KeyValues don't support arrays as JSON does and therefore this example sets the index of the value as the key in the resulting KeyValues structure.
public OnPluginStart() {
// Load some random keyvalues file
new String:sPath[PLATFORM_MAX_PATH];
Format(sPath, sizeof(sPath), "scripts/items/items_game.txt");
new Handle:hKV = CreateKeyValues("");
FileToKeyValues(hKV, sPath);
// Convert it to JSON
new Handle:hObj = KeyValuesToJSON(hKV);
// And finally save the JSON object to a file
// with indenting set to 2.
Format(sPath, sizeof(sPath), "scripts/items/items_game.json");
json_dump_file(hObj, sPath, 2);
// Close the Handle to the JSON object, i.e. free it's memory
// and free the Handle.
CloseHandle(hObj);
}
stock Handle:KeyValuesToJSON(Handle:kv) {
new Handle:hObj = json_object();
//Traverse the keyvalues structure
IterateKeyValues(kv, hObj);
//return output
return hObj;
}
IterateKeyValues(&Handle:kv, &Handle:hObj) {
do {
new String:sSection[255];
KvGetSectionName(kv, sSection, sizeof(sSection));
new String:sValue[255];
KvGetString(kv, "", sValue, sizeof(sValue));
if(!bIsSubSection) {
//if(type != KvData_None) {
json_object_set_new(hObj, sSection, json_string(sValue));
} else {
//We have no value, this must be another section
new Handle:hChild = json_object();
if (KvGotoFirstSubKey(kv, false)) {
IterateKeyValues(kv, hChild);
KvGoBack(kv);
}
json_object_set_new(hObj, sSection, hChild);
}
} while (KvGotoNextKey(kv, false));
}
Using json_pack to create JSON
Pack String Rules
n Output a JSON null value. No argument is consumed.
s Output a JSON string, consuming one argument.
b Output a JSON bool value, consuming one argument.
i Output a JSON integer value, consuming one argument.
f Output a JSON real value, consuming one argument.
r Output a JSON real value, consuming one argument.
[<packstring>]
Build an array with contents from the inner format string.
Recursive value building is supported.
No argument is consumed.
{<packstring>}
Build an array with contents from the inner format string.
The first, third, etc. format character represent a key, and must be s (as object keys are always strings).
The second, fourth, etc. format character represent a value.
Recursive value building is supported.
No argument is consumed.
Examples
PHP Code:
// Create an ADT array containing all values
// used in the json_pack string.
new Handle:hParamsArray = CreateArray(8);
PushArrayString(hParamsArray, "String");
PushArrayCell(hParamsArray, 42);
PushArrayCell(hParamsArray, 13.37);
PushArrayCell(hParamsArray, 20001.333);
PushArrayCell(hParamsArray, true);
PushArrayCell(hParamsArray, false);
// Create an ADT object containing all values
// used in the json_pack string.
new Handle:hParamsObject = CreateArray(16);
PushArrayString(hParamsObject, "FirstElement");
PushArrayCell(hParamsObject, 1);
PushArrayString(hParamsObject, "SecondElement");
PushArrayCell(hParamsObject, 2);
// Create JSON object with
// "FirstElement": 1
// "SecondElement": 2
// Note: You can omit the ':' and ',', they are just
// for readability.
new Handle:hPackObject = json_pack("{s:i,s:i}", hParamsObject);
// You can obviously nest and mix all of this and
// do something like this:
new Handle:hParams = CreateArray(64);
PushArrayString(hParams, "__String");
PushArrayString(hParams, "What is the \"Hitchhiker's guide to the galaxy\"?");
PushArrayString(hParams, "__Integer");
PushArrayCell(hParams, 9001);
PushArrayString(hParams, "__NestedObject");
PushArrayString(hParams, "__NestedString");
PushArrayString(hParams, "i am nested");
PushArrayString(hParams, "__Array");
PushArrayCell(hParams, 3);
PushArrayString(hParams, "4");
PushArrayString(hParams, "Extension 1");
PushArrayString(hParams, "Extension 2");
new Handle:hPacked = json_pack("{s:s,s:i,s:{s:s,s:[i,s,s,s]}}", hParams);
The last example will result in this:
Code:
{
"__String": "What is the \"Hitchhiker's guide to the galaxy\"?",
"__Integer": 9001,
"__NestedObject": {
"__NestedString": "i am nested",
"__Array": [
3,
"4",
"Extension 1",
"Extension 2"
]
}
}
Good job, this can be useful for reading data object via HTTP from sourcemod plugins.
__________________
Why reinvent the wheel ? Download smlib with over 350 useful functions.
When people ask me "Plz" just because it's shorter than "Please" I feel perfectly justified to answer "No" because it's shorter than "Yes"
powered by Core i7 3770k | 32GB DDR3 1886Mhz | 2x Vertex4 SSD Raid0
Added detailed error message when a json string or file could not be loaded
Added stocks to create JSON strings according to the formatting rules (json_string_format() & json_string_format_ex()).
Added stocks to get values directly from arrays or objects, instead of having to fetch the JSON representation of it first. (json_array_get_* & json_object_get_*)
Also fixed json_string() to allow const Strings as parameter.