#if defined _jansson_included_ #endinput #endif #define _jansson_included_ /** * --- Type * * The JSON specification (RFC 4627) defines the following data types: * object, array, string, number, boolean, and null. * JSON types are used dynamically; arrays and objects can hold any * other data type, including themselves. For this reason, Jansson's * type system is also dynamic in nature. There's one Handle type to * represent all JSON values, and the referenced structure knows the * type of the JSON value it holds. * */ enum JSONType { JSONType_Object, JSONType_Array, JSONType_String, JSONType_Integer, JSONType_Float, JSONType_True, JSONType_False, JSONType_Null }; /** * Return the type of the JSON value. * * @param hObj Handle to the JSON value * * @return JSONType of the value. */ native JSONType json_typeof(JSONValue hObj); /** * The type of a JSON value is queried and tested using these macros * * @param %1 Handle to the JSON value * * @return True if the value has the correct type. */ #define json_is_object(%1) ( json_typeof(%1) == JSONType_Object ) #define json_is_array(%1) ( json_typeof(%1) == JSONType_Array ) #define json_is_string(%1) ( json_typeof(%1) == JSONType_String ) #define json_is_integer(%1) ( json_typeof(%1) == JSONType_Integer ) #define json_is_real(%1) ( json_typeof(%1) == JSONType_Float ) #define json_is_true(%1) ( json_typeof(%1) == JSONType_True ) #define json_is_false(%1) ( json_typeof(%1) == JSONType_False ) #define json_is_null(%1) ( json_typeof(%1) == JSONType_Null ) #define json_is_number(%1) ( json_typeof(%1) == JSONType_Integer || json_typeof(%1) == JSONType_Float ) #define json_is_boolean(%1) ( json_typeof(%1) == JSONType_True || json_typeof(%1) == JSONType_False ) /** * Saves json_type as a String in output * * @param input json_type value to convert to string * @param output Buffer to store the json_type value * @param maxlength Maximum length of string buffer. * * @return False if the type does not exist. */ stock bool Stringify_json_type(JSONType input, char[] output, int maxlength) { switch(input) { case JSONType_Object: strcopy(output, maxlength, "Object"); case JSONType_Array: strcopy(output, maxlength, "Array"); case JSONType_String: strcopy(output, maxlength, "String"); case JSONType_Integer: strcopy(output, maxlength, "Integer"); case JSONType_Float: strcopy(output, maxlength, "Float"); case JSONType_True: strcopy(output, maxlength, "True"); case JSONType_False: strcopy(output, maxlength, "False"); case JSONType_Null: strcopy(output, maxlength, "Null"); default: return false; } return true; } /** * --- Equality * * - Two integer or real values are equal if their contained numeric * values are equal. An integer value is never equal to a real value, * though. * - Two strings are equal if their contained UTF-8 strings are equal, * byte by byte. Unicode comparison algorithms are not implemented. * - Two arrays are equal if they have the same number of elements and * each element in the first array is equal to the corresponding * element in the second array. * - Two objects are equal if they have exactly the same keys and the * value for each key in the first object is equal to the value of * the corresponding key in the second object. * - Two true, false or null values have no "contents", so they are * equal if their types are equal. * */ /** * Test whether two JSON values are equal. * * @param hObj Handle to the first JSON node * @param hOther Handle to the second JSON node * * @return Returns false if they are inequal or one * or both of the pointers are NULL. */ native bool json_equal(JSONValue hObj, JSONValue hOther); /** * --- Copying * * Jansson supports two kinds of copying: shallow and deep. There is * a difference between these methods only for arrays and objects. * * Shallow copying only copies the first level value (array or object) * and uses the same child values in the copied value. * * Deep copying makes a fresh copy of the child values, too. Moreover, * all the child values are deep copied in a recursive fashion. * */ /** * Get a shallow copy of the passed object * * @param hObj Handle to JSON object to be copied * * @return Returns a shallow copy of the object, * or INVALID_HANDLE on error. */ native JSONValue json_copy(JSONValue hObj); /** * Get a deep copy of the passed object * * @param hObj Handle to JSON object to be copied * * @return Returns a deep copy of the object, * or INVALID_HANDLE on error. */ native JSONValue json_deep_copy(JSONValue hObj); /** * --- Objects * * A JSON object is a dictionary of key-value pairs, where the * key is a Unicode string and the value is any JSON value. * */ /** * Returns a handle to a new JSON object, or INVALID_HANDLE on error. * Initially, the object is empty. * * @return Handle to a new JSON object. */ native JSONObject json_object(); /** * Returns the number of elements in hObj * * @param hObj Handle to JSON object * * @return Number of elements in hObj, * or 0 if hObj is not a JSON object. */ native int json_object_size(JSONObject hObj); /** * Get a value corresponding to sKey from hObj * * @param hObj Handle to JSON object to get a value from * @param sKey Key to retrieve * * @return Handle to a the JSON object or * INVALID_HANDLE on error. */ native JSONValue json_object_get(JSONObject hObj, const char[] sKey); /** * Set the value of sKey to hValue in hObj. * If there already is a value for key, it is replaced by the new value. * * @param hObj Handle to JSON object to set a value on * @param sKey Key to store in the object * Must be a valid null terminated UTF-8 encoded * Unicode string. * @param hValue Value to store in the object * * @return True on success. */ native bool json_object_set(JSONObject hObj, const char[] sKey, JSONValue hValue); /** * Set the value of sKey to hValue in hObj. * If there already is a value for key, it is replaced by the new value. * This function automatically closes the Handle to the value object. * * @param hObj Handle to JSON object to set a value on * @param sKey Key to store in the object * Must be a valid null terminated UTF-8 encoded * Unicode string. * @param hValue Value to store in the object * * @return True on success. */ native bool json_object_set_new(JSONObject hObj, const char[] sKey, JSONValue hValue); /** * Delete sKey from hObj if it exists. * * @param hObj Handle to JSON object to delete a key from * @param sKey Key to delete * * @return True on success. */ native bool json_object_del(JSONObject hObj, const char[] sKey); /** * Remove all elements from hObj. * * @param hObj Handle to JSON object to remove all * elements from. * * @return True on success. */ native bool json_object_clear(JSONObject hObj); /** * Update hObj with the key-value pairs from hOther, overwriting * existing keys. * * @param hObj Handle to JSON object to update * @param hOther Handle to JSON object to get update * keys/values from. * * @return True on success. */ native bool json_object_update(JSONObject hObj, JSONObject hOther); /** * Like json_object_update(), but only the values of existing keys * are updated. No new keys are created. * * @param hObj Handle to JSON object to update * @param hOther Handle to JSON object to get update * keys/values from. * * @return True on success. */ native bool json_object_update_existing(JSONObject hObj, JSONObject hOther); /** * Like json_object_update(), but only new keys are created. * The value of any existing key is not changed. * * @param hObj Handle to JSON object to update * @param hOther Handle to JSON object to get update * keys/values from. * * @return True on success. */ native bool json_object_update_missing(JSONObject hObj, JSONObject hOther); /** * Object iteration * * Example code: * - We assume hObj is a Handle to a valid JSON object. * * * new Handle:hIterator = json_object_iter(hObj); * while(hIterator != INVALID_HANDLE) * { * new String:sKey[128]; * json_object_iter_key(hIterator, sKey, sizeof(sKey)); * * new Handle:hValue = json_object_iter_value(hIterator); * * // Do something with sKey and hValue * * CloseHandle(hValue); * * hIterator = json_object_iter_next(hObj, hIterator); * } * */ /** * Returns a handle to an iterator which can be used to iterate over * all key-value pairs in hObj. * If you are not iterating to the end of hObj make sure to close the * handle to the iterator manually. * * @param hObj Handle to JSON object to get an iterator * for. * * @return Handle to JSON object iterator, * or INVALID_HANDLE on error. */ native JSONObjectIterator json_object_iter(JSONObject hObj); /** * Like json_object_iter(), but returns an iterator to the key-value * pair in object whose key is equal to key. * Iterating forward to the end of object only yields all key-value * pairs of the object if key happens to be the first key in the * underlying hash table. * * @param hObj Handle to JSON object to get an iterator * for. * @param sKey Start key for the iterator * * @return Handle to JSON object iterator, * or INVALID_HANDLE on error. */ native JSONObjectIterator json_object_iter_at(JSONObject hObj, const char[] sKey); /** * Returns an iterator pointing to the next key-value pair in object. * This automatically closes the Handle to the iterator hIter. * * @param hObj Handle to JSON object. * @param hIter Handle to JSON object iterator. * * @return Handle to JSON object iterator, * or INVALID_HANDLE on error, or if the * whole object has been iterated through. */ native JSONObjectIterator json_object_iter_next(JSONObject hObj, JSONObjectIterator hIter); /** * Extracts the associated key of hIter as a null terminated UTF-8 * encoded string in the passed buffer. * * @param hIter Handle to the JSON String object * @param sKeyBuffer Buffer to store the value of the String. * @param maxlength Maximum length of string buffer. * @error Invalid JSON Object Iterator. * @return Length of the returned string or -1 on error. */ native int json_object_iter_key(JSONObjectIterator hIter, char[] sKeyBuffer, int maxlength); /** * Returns a handle to the value hIter is pointing at. * * @param hIter Handle to JSON object iterator. * * @return Handle to value or INVALID_HANDLE on error. */ native JSONValue json_object_iter_value(JSONObjectIterator hIter); /** * Set the value of the key-value pair in hObj, that is pointed to * by hIter, to hValue. * * @param hObj Handle to JSON object. * @param hIter Handle to JSON object iterator. * @param hValue Handle to JSON value. * * @return True on success. */ native bool json_object_iter_set(JSONObject hObj, JSONObjectIterator hIter, JSONValue hValue); /** * Set the value of the key-value pair in hObj, that is pointed to * by hIter, to hValue. * This function automatically closes the Handle to the value object. * * @param hObj Handle to JSON object. * @param hIter Handle to JSON object iterator. * @param hValue Handle to JSON value. * * @return True on success. */ native bool json_object_iter_set_new(JSONObject hObj, JSONObjectIterator hIter, JSONValue hValue); /** * Arrays * * A JSON array is an ordered collection of other JSON values. * */ /** * Returns a handle to a new JSON array, or INVALID_HANDLE on error. * * @return Handle to the new JSON array */ native JSONArray json_array(); /** * Returns the number of elements in hArray * * @param hObj Handle to JSON array * * @return Number of elements in hArray, * or 0 if hObj is not a JSON array. */ native int json_array_size(JSONArray hArray); /** * Returns the element in hArray at position iIndex. * * @param hArray Handle to JSON array to get a value from * @param iIndex Position to retrieve * * @return Handle to a the JSON object or * INVALID_HANDLE on error. */ native JSONValue json_array_get(JSONArray hArray, int iIndex); /** * Replaces the element in array at position iIndex with hValue. * The valid range for iIndex is from 0 to the return value of * json_array_size() minus 1. * * @param hArray Handle to JSON array * @param iIndex Position to replace * @param hValue Value to store in the array * * @return True on success. */ native bool json_array_set(JSONArray hArray, int iIndex, JSONValue hValue); /** * Replaces the element in array at position iIndex with hValue. * The valid range for iIndex is from 0 to the return value of * json_array_size() minus 1. * This function automatically closes the Handle to the value object. * * @param hArray Handle to JSON array * @param iIndex Position to replace * @param hValue Value to store in the array * * @return True on success. */ native bool json_array_set_new(JSONArray hArray, int iIndex, JSONValue hValue); /** * Appends value to the end of array, growing the size of array by 1. * * @param hArray Handle to JSON array * @param hValue Value to append to the array * * @return True on success. */ native bool json_array_append(JSONArray hArray, JSONValue hValue); /** * Appends value to the end of array, growing the size of array by 1. * This function automatically closes the Handle to the value object. * * @param hArray Handle to JSON array * @param hValue Value to append to the array * * @return True on success. */ native bool json_array_append_new(JSONArray hArray, JSONValue hValue); /** * Inserts value to hArray at position iIndex, shifting the elements at * iIndex and after it one position towards the end of the array. * * @param hArray Handle to JSON array * @param iIndex Position to insert at * @param hValue Value to store in the array * * @return True on success. */ native bool json_array_insert(JSONArray hArray, int iIndex, JSONValue hValue); /** * Inserts value to hArray at position iIndex, shifting the elements at * iIndex and after it one position towards the end of the array. * This function automatically closes the Handle to the value object. * * @param hArray Handle to JSON array * @param iIndex Position to insert at * @param hValue Value to store in the array * * @return True on success. */ native bool json_array_insert_new(JSONArray hArray, int iIndex, JSONValue hValue); /** * Removes the element in hArray at position iIndex, shifting the * elements after iIndex one position towards the start of the array. * * @param hArray Handle to JSON array * @param iIndex Position to insert at * * @return True on success. */ native bool json_array_remove(JSONArray hArray, int iIndex); /** * Removes all elements from hArray. * * @param hArray Handle to JSON array * * @return True on success. */ native bool json_array_clear(JSONArray hArray); /** * Appends all elements in hOther to the end of hArray. * * @param hArray Handle to JSON array to be extended * @param hOther Handle to JSON array, source to copy from * * @return True on success. */ native bool json_array_extend(JSONArray hArray, JSONArray hOther); /** * Booleans & NULL * */ /** * Returns a handle to a new JSON Boolean with value true, * or INVALID_HANDLE on error. * * @return Handle to the new Boolean object */ native JSONValue json_true(); /** * Returns a handle to a new JSON Boolean with value false, * or INVALID_HANDLE on error. * * @return Handle to the new Boolean object */ native JSONValue json_false(); /** * Returns a handle to a new JSON Boolean with the value passed * in bState or INVALID_HANDLE on error. * * @param bState Value for the new Boolean object * @return Handle to the new Boolean object */ native JSONValue json_boolean(bool bState); /** * Returns a handle to a new JSON NULL or INVALID_HANDLE on error. * * @return Handle to the new NULL object */ native JSONValue json_null(); /** * Strings * * Jansson uses UTF-8 as the character encoding. All JSON strings must * be valid UTF-8 (or ASCII, as it's a subset of UTF-8). Normal null * terminated C strings are used, so JSON strings may not contain * embedded null characters. * */ /** * Returns a handle to a new JSON string, or INVALID_HANDLE on error. * * @param sValue Value for the new String object * Must be a valid UTF-8 encoded Unicode string. * @return Handle to the new String object */ native JSONString json_string(const char[] sValue); /** * Saves the associated value of hString as a null terminated UTF-8 * encoded string in the passed buffer. * * @param hString Handle to the JSON String object * @param sValueBuffer Buffer to store the value of the String. * @param maxlength Maximum length of string buffer. * @error Invalid JSON String Object. * @return Length of the returned string or -1 on error. */ native int json_string_value(JSONString hString, char[] sValueBuffer, int maxlength); /** * Sets the associated value of JSON String object to value. * * @param hString Handle to the JSON String object * @param sValue Value to set the object to. * Must be a valid UTF-8 encoded Unicode string. * @error Invalid JSON String Object. * @return True on success. */ native bool json_string_set(JSONString hString, const char[] sValue); /** * Numbers * * The JSON specification only contains one numeric type, 'number'. * The C (and Pawn) programming language has distinct types for integer * and floating-point numbers, so for practical reasons Jansson also has * distinct types for the two. They are called 'integer' and 'real', * respectively. (Whereas 'real' is a 'Float' for Pawn). * Therefore a number is represented by either a value of the type * JSONType_Integer or of the type JSONType_Float. * */ /** * Returns a handle to a new JSON integer, or INVALID_HANDLE on error. * * @param iValue Value for the new Integer object * @return Handle to the new Integer object */ native JSONInteger json_integer(int iValue); /** * Returns the associated value of a JSON Integer Object. * * @param hInteger Handle to the JSON Integer object * @error Invalid JSON Integer Object. * @return Value of the hInteger, * or 0 if hInteger is not a JSON integer. */ native int json_integer_value(JSONInteger hInteger); /** * Sets the associated value of JSON Integer to value. * * @param hInteger Handle to the JSON Integer object * @param iValue Value to set the object to. * @error Invalid JSON Integer Object. * @return True on success. */ native bool json_integer_set(JSONInteger hInteger, int iValue); /** * Returns a handle to a new JSON real, or INVALID_HANDLE on error. * * @param fValue Value for the new Real object * @return Handle to the new String object */ native JSONFloat json_real(float fValue); /** * Returns the associated value of a JSON Real. * * @param hReal Handle to the JSON Real object * @error Invalid JSON Real Object. * @return Float value of hReal, * or 0.0 if hReal is not a JSON Real. */ native float json_real_value(JSONFloat hReal); /** * Sets the associated value of JSON Real to fValue. * * @param hReal Handle to the JSON Integer object * @param fValue Value to set the object to. * @error Invalid JSON Real handle. * @return True on success. */ native bool json_real_set(JSONFloat hReal, float value); /** * Returns the associated value of a JSON integer or a * JSON Real, cast to Float regardless of the actual type. * * @param hNumber Handle to the JSON Number * @error Not a JSON Real or JSON Integer * @return Float value of hNumber, * or 0.0 on error. */ native float json_number_value(JSONNumber hNumber); /** * Decoding * * This sections describes the functions that can be used to decode JSON text * to the Jansson representation of JSON data. The JSON specification requires * that a JSON text is either a serialized array or object, and this * requirement is also enforced with the following functions. In other words, * the top level value in the JSON text being decoded must be either array or * object. * */ /** * Decodes the JSON string sJSON and returns the array or object it contains. * Errors while decoding can be found in the sourcemod error log. * * @param sJSON String containing valid JSON * @return Handle to JSON object or array. * or INVALID_HANDLE on error. */ native JSONValue json_load(const char[] sJSON); /** * Decodes the JSON string sJSON and returns the array or object it contains. * This function provides additional error feedback and does not log errors * to the sourcemod error log. * * @param sJSON String containing valid JSON * @param sErrorText This buffer will be filled with the error * message. * @param maxlen Size of the buffer * @param iLine This int will contain the line of the error * @param iColumn This int will contain the column of the error * * @return Handle to JSON object or array. * or INVALID_HANDLE on error. */ native JSONValue json_load_ex(const char[] sJSON, char[] sErrorText, int maxlen, int &iLine, int &iColumn); /** * Decodes the JSON text in file sFilePath and returns the array or object * it contains. * Errors while decoding can be found in the sourcemod error log. * * @param sFilePath Path to a file containing pure JSON * * @return Handle to JSON object or array. * or INVALID_HANDLE on error. */ native JSONValue json_load_file(const char sFilePath[PLATFORM_MAX_PATH]); /** * Decodes the JSON text in file sFilePath and returns the array or object * it contains. * This function provides additional error feedback and does not log errors * to the sourcemod error log. * * @param sFilePath Path to a file containing pure JSON * @param sErrorText This buffer will be filled with the error * message. * @param maxlen Size of the buffer * @param iLine This int will contain the line of the error * @param iColumn This int will contain the column of the error * * @return Handle to JSON object or array. * or INVALID_HANDLE on error. */ native JSONValue json_load_file_ex(const char sFilePath[PLATFORM_MAX_PATH], char[] sErrorText, int maxlen, int &iLine, int &iColumn); /** * Encoding * * This sections describes the functions that can be used to encode values * to JSON. By default, only objects and arrays can be encoded directly, * since they are the only valid root values of a JSON text. * */ /** * Saves the JSON representation of hObject in sJSON. * * @param hObject String containing valid JSON * @param sJSON Buffer to store the created JSON string. * @param maxlength Maximum length of string buffer. * @param iIndentWidth Indenting with iIndentWidth spaces. * The valid range for this is between 0 and 31 (inclusive), * other values result in an undefined output. If this is set * to 0, no newlines are inserted between array and object items. * @param bEnsureAscii If this is set, the output is guaranteed * to consist only of ASCII characters. This is achieved * by escaping all Unicode characters outside the ASCII range. * @param bSortKeys If this flag is used, all the objects in output are sorted * by key. This is useful e.g. if two JSON texts are diffed * or visually compared. * @param bPreserveOrder If this flag is used, object keys in the output are sorted * into the same order in which they were first inserted to * the object. For example, decoding a JSON text and then * encoding with this flag preserves the order of object keys. * @return Length of the returned string or -1 on error. */ native int json_dump(JSONValue hObject, char[] sJSON, int maxlength, int iIndentWidth = 4, bool bEnsureAscii = false, bool bSortKeys = false, bool bPreserveOrder = false); /** * Write the JSON representation of hObject to the file sFilePath. * If sFilePath already exists, it is overwritten. * * @param hObject String containing valid JSON * @param sFilePath Buffer to store the created JSON string. * @param iIndentWidth Indenting with iIndentWidth spaces. * The valid range for this is between 0 and 31 (inclusive), * other values result in an undefined output. If this is set * to 0, no newlines are inserted between array and object items. * @param bEnsureAscii If this is set, the output is guaranteed * to consist only of ASCII characters. This is achieved * by escaping all Unicode characters outside the ASCII range. * @param bSortKeys If this flag is used, all the objects in output are sorted * by key. This is useful e.g. if two JSON texts are diffed * or visually compared. * @param bPreserveOrder If this flag is used, object keys in the output are sorted * into the same order in which they were first inserted to * the object. For example, decoding a JSON text and then * encoding with this flag preserves the order of object keys. * @return Length of the returned string or -1 on error. */ native bool json_dump_file(JSONValue hObject, const char[] sFilePath, int iIndentWidth = 4, bool bEnsureAscii = false, bool bSortKeys = false, bool bPreserveOrder = false); /** * MethodMaps * * Again: EXPERIMENTAL! * */ enum JSONObjectUpdateType { Update_All = 0, Update_Existing, Update_Missing }; /** * Base methodmap for all of smjansson's handles */ methodmap JSONValue < Handle { property JSONType Type { public get() { return json_typeof(this); } } property bool IsObject { public get() { return (this.Type == JSONType_Object); } } property bool IsArray { public get() { return (this.Type == JSONType_Array); } } property bool IsString { public get() { return (this.Type == JSONType_String); } } property bool IsInteger { public get() { return (this.Type == JSONType_Integer); } } property bool IsFloat { public get() { return (this.Type == JSONType_Float); } } property bool IsTrue { public get() { return (this.Type == JSONType_True); } } property bool IsFalse { public get() { return (this.Type == JSONType_False); } } property bool IsNull { public get() { return (this.Type == JSONType_Null); } } property bool IsNumber { public get() { return (this.Type == JSONType_Integer || this.Type == JSONType_Float); } } property bool IsBoolean { public get() { return (this.Type == JSONType_True || this.Type == JSONType_False); } } property any Value { // not implemented } public bool Equals(JSONValue other) { return json_equal(this, other); } public JSONValue Copy(bool deep = false) { if (deep) { return view_as(json_deep_copy(this)); } else { return view_as(json_copy(this)); } } public void TypeToString(char[] buffer, int maxlength) { if (!Stringify_json_type(view_as(this.Type), buffer, maxlength)) { ThrowError("Attempting to get type of a non-SMJansson handle"); } } } methodmap JSONBoolean < JSONValue { public JSONBoolean(bool value) { return view_as(json_boolean(value)); } property bool Value { public get() { if (this.Type == JSONType_True) { return true; } else if (this.Type == JSONType_False) { return false; } ThrowError("Not a JSONBoolean value"); return false; } } } methodmap JSONNull < JSONValue { public JSONNull() { return view_as(json_null()); } } methodmap JSONString < JSONValue { public JSONString(const char[] value) { return view_as(json_string(value)); } public static JSONString Format(int bufferSize = 4096, const char[] format, any ...) { char[] buffer = new char[bufferSize]; VFormat(buffer, bufferSize, format, 3); return new JSONString(buffer); } public int GetString(char[] buffer, int length) { return json_string_value(this, buffer, length); } public bool SetString(char[] value) { return json_string_set(this, value); } } /** * Base map inherited by JSONInteger and JSONFloat to get the value of either, cast to float. */ methodmap JSONNumber < JSONValue { public float FloatValue() { return json_number_value(this); } } methodmap JSONInteger < JSONNumber { public JSONInteger(int value) { return view_as(json_integer(value)); } property int Value { public get() { return json_integer_value(this); } public set(int value) { json_integer_set(this, value); } } } methodmap JSONFloat < JSONNumber { public JSONFloat(float value) { return view_as(json_real(value)); } property float Value { public get() { return json_real_value(this); } public set(float value) { json_real_set(this, value); } } } /** * Provides a few functions for valid root nodes (JSONArray and JSONObject) */ methodmap JSONRootNode < JSONValue { /** * Dumps the contents of the given root node to a string. * * @return Number of characters written */ public int ToString(char[] buffer, int maxlength, int indentWidth = 4, bool asciiOnly = false, bool sortKeys = false, bool preserveOrder = false) { return json_dump(this, buffer, maxlength, indentWidth, asciiOnly, sortKeys, preserveOrder); } /** * @return True on success */ public bool ToFile(const char[] filePath, int indentWidth = 4, bool asciiOnly = false, bool sortKeys = false, bool preserveOrder = false) { return json_dump_file(this, filePath, indentWidth, asciiOnly, sortKeys, preserveOrder); } public static JSONRootNode FromFile(const char[] filePath) { char path[PLATFORM_MAX_PATH]; strcopy(path, sizeof(path), filePath); return view_as(json_load_file(path)); } public static JSONRootNode Pack(const char[] packString, ArrayList params) { return json_pack(packString, params); } public void DumpToServer() { char sMsg[4096]; this.ToString(sMsg, sizeof(sMsg)); PrintToServer(sMsg); } } methodmap JSONArray < JSONRootNode { public JSONArray() { return view_as(json_array()); } property int Length { public get() { if (this.Type != JSONType_Array) { ThrowError("Handle is not an array"); } return json_array_size(this); } } public JSONValue Get(int index) { return view_as(json_array_get(this, index)); } public bool Set(int index, JSONValue value, bool autoClose = true) { if (autoClose) { return json_array_set_new(this, index, value); } return json_array_set(this, index, value); } public bool Append(JSONValue value, bool autoClose = true) { if (autoClose) { return json_array_append_new(this, value); } return json_array_append(this, value); } public bool Insert(int index, JSONValue value, bool autoClose = true) { if (autoClose) { return json_array_insert_new(this, index, value); } return json_array_insert(this, index, value); } public bool Remove(int index) { return json_array_remove(this, index); } public bool Clear() { return json_array_clear(this); } public bool Extend(JSONArray other) { return json_array_extend(this, other); } /** * Utility functions */ /* Booleans */ public bool GetBool(int index, bool defValue = false) { JSONValue value = this.Get(index); if(!value) return defValue; JSONType type = value.Type; delete value; switch (type) { case JSONType_True: { return true; } case JSONType_False: { return false; } } return defValue; } public bool SetBool(int index, bool value) { return this.Set(index, new JSONBoolean(value)); } public bool AppendBool(bool value) { return this.Append(new JSONBoolean(value)); } public bool InsertBool(int index, bool value) { return this.Insert(index, new JSONBoolean(value)); } /* Floats */ public float GetFloat(int index, float defValue = 0.0) { JSONValue value = this.Get(index); if(!value) return defValue; float result = (json_is_number(value) ? (view_as(value)).FloatValue() : defValue); delete value; return result; } public bool SetFloat(int index, float value) { return this.Set(index, new JSONFloat(value)); } public bool AppendFloat(float value) { return this.Append(new JSONFloat(value)); } public bool InsertFloat(int index, float value) { return this.Insert(index, new JSONFloat(value)); } /* Integers */ public int GetInt(int index, int defValue = 0) { JSONValue value = this.Get(index); if(!value) return defValue; int result = value.Type == JSONType_Integer ? (view_as(value)).Value : 0; delete value; return result; } public bool SetInt(int index, int value) { return this.Set(index, new JSONInteger(value)); } public bool AppendInt(int value) { return this.Append(new JSONInteger(value)); } public bool InsertInt(int index, int value) { return this.Insert(index, new JSONInteger(value)); } /* Strings */ public int GetString(int index, char[] buffer, int maxlength) { JSONValue value = this.Get(index); if(!value) return -1; int result = -1; if (value.Type == JSONType_String) { result = (view_as(value)).GetString(buffer, maxlength); } delete value; return result; } public bool SetString(int index, const char[] value) { return this.Set(index, new JSONString(value)); } public bool AppendString(const char[] value) { return this.Append(new JSONString(value)); } public bool InsertString(int index, const char[] value) { return this.Insert(index, new JSONString(value)); } /* Misc. functions */ public static JSONArray FromFile(const char[] filePath) { JSONRootNode data = JSONRootNode.FromFile(filePath); if (data.Type == JSONType_Array) { return view_as(data); } else { ThrowError("File loaded by JSONArray.FromFile was not an array"); delete data; return null; } } public static JSONArray Pack(const char[] packString, ArrayList params) { int length = strlen(packString); if (packString[0] == '[' && packString[length - 1] == ']') { return view_as(JSONRootNode.Pack(packString, params)); } else { ThrowError("Pack string '%s' is not appropriate for creating a JSONArray", packString); return null; } } } methodmap JSONObject < JSONRootNode { public JSONObject() { return view_as(json_object()); } property int Size { public get() { return json_object_size(this); } } public JSONValue Get(const char[] key) { return view_as(json_object_get(this, key)); } public bool Set(const char[] key, JSONValue value, bool autoClose = true) { if (autoClose) { return json_object_set_new(this, key, value); } return json_object_set(this, key, value); } /** * @return true on success */ public bool Remove(const char[] key) { return json_object_del(this, key); } public bool Clear() { return json_object_clear(this); } public bool Update(JSONObject other, JSONObjectUpdateType updateType = Update_All) { switch (updateType) { case Update_Existing: { return json_object_update_existing(this, other); } case Update_Missing: { return json_object_update_missing(this, other); } } return json_object_update(this, other); } /** * Utility functions */ public bool GetBool(const char[] key, bool defValue = false) { JSONValue value = this.Get(key); if(!value) return defValue; JSONType type = value.Type; delete value; switch (type) { case JSONType_True: { return true; } case JSONType_False: { return false; } } return defValue; } public bool SetBool(const char[] key, bool value) { return this.Set(key, new JSONBoolean(value)); } /* Floats */ public float GetFloat(const char[] key, float defValue = 0.0) { JSONValue value = this.Get(key); if(!value) return defValue; float result = (json_is_number(value) ? (view_as(value)).FloatValue() : defValue); delete value; return result; } public bool SetFloat(const char[] key, float value) { return this.Set(key, new JSONFloat(value)); } /* Integers */ public int GetInt(const char[] key, int defValue = 0) { JSONValue value = this.Get(key); if(!value) return defValue; int result = value.Type == JSONType_Integer ? (view_as(value)).Value : defValue; delete value; return result; } public bool SetInt(const char[] key, int value) { return this.Set(key, new JSONInteger(value)); } /* Strings */ public int GetString(const char[] key, char[] buffer, int maxlength) { JSONValue value = this.Get(key); if(!value) return -1; int result = -1; if (value.Type == JSONType_String) { result = (view_as(value)).GetString(buffer, maxlength); } delete value; return result; } public bool SetString(const char[] key, const char[] value) { return this.Set(key, new JSONString(value)); } /* Misc. functions */ public static JSONObject FromFile(const char[] filePath) { JSONRootNode data = JSONRootNode.FromFile(filePath); if (data.Type == JSONType_Object) { return view_as(data); } else { ThrowError("File loaded by JSONObject.FromFile was not an object"); delete data; return null; } } public static JSONObject Pack(const char[] packString, ArrayList params) { int length = strlen(packString); if (packString[0] == '{' && packString[length - 1] == '}') { return view_as(JSONRootNode.Pack(packString, params)); } else { ThrowError("Pack string '%s' is not appropriate for creating a JSONObject", packString); return null; } } } methodmap JSONObjectIterator < Handle { public static JSONObjectIterator From(JSONObject obj, const char[] key = "") { if (strlen(key) > 0) { return view_as(json_object_iter_at(obj, key)); } return view_as(json_object_iter(obj)); } public JSONObjectIterator Next(JSONObject obj) { return view_as(json_object_iter_next(obj, this)); } public int GetKey(char[] buffer, int maxlength) { return json_object_iter_key(this, buffer, maxlength); } public JSONValue GetValue() { return view_as(json_object_iter_value(this)); } public bool SetValue(JSONObject obj, JSONValue value, bool autoclose = true) { if (autoclose) { return json_object_iter_set_new(obj, this, value); } return json_object_iter_set(obj, this, value); } } /** * Some additional constructors * * */ /** * Returns a handle to a new JSON string, or INVALID_HANDLE on error. * Formats the string according to the SourceMod format rules. * The result must be a valid UTF-8 encoded Unicode string. * * @param sFormat Formatting rules. * @param ... Variable number of format parameters. * @return Handle to the new String object */ public JSONString JSONString_ByFormat(const char[] sFormat, ...) { char sTmp[4096]; VFormat(sTmp, sizeof(sTmp), sFormat, 2); return new JSONString(sTmp); } /** * Returns a handle to a new JSON string, or INVALID_HANDLE on error. * This stock allows to specify the size of the temporary buffer used * to create the string. Use this if the default of 4096 is not enough * for your string. * Formats the string according to the SourceMod format rules. * The result must be a valid UTF-8 encoded Unicode string. * * @param tmpBufferLength Size of the temporary buffer * @param sFormat Formatting rules. * @param ... Variable number of format parameters. * @return Handle to the new String object */ public JSONString JSONString_ByFormatEx(int tmpBufferLength, const char[] sFormat, ...) { char[] sTmp = new char[tmpBufferLength]; VFormat(sTmp, tmpBufferLength, sFormat, 3); return new JSONString(sTmp); } /** * Pack String Rules * * Here's the full list of format characters: * 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. * [] Build an array with contents from the inner format string, * recursive value building is supported. * No argument is consumed. * {} 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. * */ /** * This method can be used to create json objects/arrays directly * without having to create the structure. * See 'Pack String Rules' for more details. * * @param sPackString Pack string similiar to Format()s fmt. * See 'Pack String Rules'. * @param hParams ADT Array containing all keys and values * in the order they appear in the pack string. * * @error Invalid pack string or pack string and * ADT Array don't match up regarding type * or size. * @return Handle to JSON element. */ public JSONValue JSONValue_ByPack(const char[] sPackString, Handle hParams) { int iPos = 0; return json_pack_element_(sPackString, iPos, hParams); } /** * Internal stocks used by json_pack(). Don't use these directly! * */ public JSONArray json_pack_array_(const char[] sFormat, int &iPos, Handle hParams) { JSONArray hObj = new JSONArray(); int iStrLen = strlen(sFormat); for(; iPos < iStrLen;) { int this_char = sFormat[iPos]; if(this_char == 32 || this_char == 58 || this_char == 44) { // Skip whitespace, ',' and ':' iPos++; continue; } if(this_char == 93) { // array end iPos++; break; } // Get the next entry as value // This automatically increments the position! JSONValue hValue = json_pack_element_(sFormat, iPos, hParams); // Append the value to the array. hObj.Append(hValue); } return hObj; } public JSONObject json_pack_object_(const char[] sFormat, int &iPos, Handle hParams) { JSONObject hObj = new JSONObject(); int iStrLen = strlen(sFormat); for(; iPos < iStrLen;) { int this_char = sFormat[iPos]; if(this_char == 32 || this_char == 58 || this_char == 44) { // Skip whitespace, ',' and ':' iPos++; continue; } if(this_char == 125) { // } --> object end iPos++; break; } if(this_char != 115) { LogError("Object keys must be strings at %d.", iPos); CloseHandle(hObj); return view_as(INVALID_HANDLE); } // Get the key string for this object from // the hParams array. char sKey[255]; GetArrayString(hParams, 0, sKey, sizeof(sKey)); RemoveFromArray(hParams, 0); // Advance one character in the pack string, // because we've just read the Key string for // this object. iPos++; // Get the next entry as value // This automatically increments the position! JSONValue hValue = json_pack_element_(sFormat, iPos, hParams); // Insert into object hObj.Set(sKey, hValue); } return hObj; } public JSONValue json_pack_element_(const char[] sFormat, int &iPos, Handle hParams) { int this_char = sFormat[iPos]; while(this_char == 32 || this_char == 58 || this_char == 44) { iPos++; this_char = sFormat[iPos]; } // Advance one character in the pack string iPos++; switch(this_char) { case 91: { // { --> Array return json_pack_array_(sFormat, iPos, hParams); } case 123: { // { --> Object return json_pack_object_(sFormat, iPos, hParams); } case 98: { // b --> Boolean int iValue = GetArrayCell(hParams, 0); RemoveFromArray(hParams, 0); return json_boolean(view_as(iValue)); } case 102, 114: { // r,f --> Real (Float) float fValue = GetArrayCell(hParams, 0); RemoveFromArray(hParams, 0); return json_real(fValue); } case 110: { // n --> NULL return json_null(); } case 115: { // s --> String char sKey[255]; GetArrayString(hParams, 0, sKey, sizeof(sKey)); RemoveFromArray(hParams, 0); return json_string(sKey); } case 105: { // i --> Integer int iValue = GetArrayCell(hParams, 0); RemoveFromArray(hParams, 0); return json_integer(iValue); } } SetFailState("Invalid pack String '%s'. Type '%s' not supported at %i", sFormat, this_char, iPos); return json_null(); } /** * Not yet implemented * * native json_object_foreach(Handle:hObj, ForEachCallback:cb); * native Handle:json_unpack(const String:sFormat[], ...); * */ /** * Do not edit below this line! */ public Extension __ext_smjansson = { name = "SMJansson", file = "smjansson.ext", #if defined AUTOLOAD_EXTENSIONS autoload = 1, #else autoload = 0, #endif #if defined REQUIRE_EXTENSIONS required = 1, #else required = 0, #endif }; #if !defined REQUIRE_EXTENSIONS public __ext_smjansson_SetNTVOptional() { MarkNativeAsOptional("json_typeof"); MarkNativeAsOptional("json_equal"); MarkNativeAsOptional("json_copy"); MarkNativeAsOptional("json_deep_copy"); MarkNativeAsOptional("json_object"); MarkNativeAsOptional("json_object_size"); MarkNativeAsOptional("json_object_get"); MarkNativeAsOptional("json_object_set"); MarkNativeAsOptional("json_object_set_new"); MarkNativeAsOptional("json_object_del"); MarkNativeAsOptional("json_object_clear"); MarkNativeAsOptional("json_object_update"); MarkNativeAsOptional("json_object_update_existing"); MarkNativeAsOptional("json_object_update_missing"); MarkNativeAsOptional("json_object_iter"); MarkNativeAsOptional("json_object_iter_at"); MarkNativeAsOptional("json_object_iter_next"); MarkNativeAsOptional("json_object_iter_key"); MarkNativeAsOptional("json_object_iter_value"); MarkNativeAsOptional("json_object_iter_set"); MarkNativeAsOptional("json_object_iter_set_new"); MarkNativeAsOptional("json_array"); MarkNativeAsOptional("json_array_size"); MarkNativeAsOptional("json_array_get"); MarkNativeAsOptional("json_array_set"); MarkNativeAsOptional("json_array_set_new"); MarkNativeAsOptional("json_array_append"); MarkNativeAsOptional("json_array_append_new"); MarkNativeAsOptional("json_array_insert"); MarkNativeAsOptional("json_array_insert_new"); MarkNativeAsOptional("json_array_remove"); MarkNativeAsOptional("json_array_clear"); MarkNativeAsOptional("json_array_extend"); MarkNativeAsOptional("json_string"); MarkNativeAsOptional("json_string_value"); MarkNativeAsOptional("json_string_set"); MarkNativeAsOptional("json_integer"); MarkNativeAsOptional("json_integer_value"); MarkNativeAsOptional("json_integer_set"); MarkNativeAsOptional("json_real"); MarkNativeAsOptional("json_real_value"); MarkNativeAsOptional("json_real_set"); MarkNativeAsOptional("json_number_value"); MarkNativeAsOptional("json_boolean"); MarkNativeAsOptional("json_true"); MarkNativeAsOptional("json_false"); MarkNativeAsOptional("json_null"); MarkNativeAsOptional("json_load"); MarkNativeAsOptional("json_load_file"); MarkNativeAsOptional("json_dump"); MarkNativeAsOptional("json_dump_file"); } #endif