NimaBastani/pawn-json-parser
Pure Pawn JSON Parser for SA-MP/open.mp servers | Full-featured JSON parsing, building, and serialization WITHOUT any plugins
README.md
JSON Parser for SA-MP/open.mp (Pawn)
A comprehensive, pure-Pawn JSON parser, builder, serializer, and query engine for SA-MP/open.mp servers. No plugins required.
About This Project
This library has been a quiet side project of mine for roughly 2 years. I started it because I needed a reliable JSON solution for my SA-MP server and nothing out there felt right - either too limited, or required external plugins I didn't want to depend on.
So I built my own, piece by piece, version by version. It was never meant to be public. Just a personal tool I kept improving whenever I hit a new edge case or needed a feature that wasn't there yet (or if I had an exam the day after).
But at some point I looked at it and thought... why not share it? Maybe someone else is in the same spot I was. So here it is, nothing fancy, just a solid pure-Pawn JSON parser that does what it's supposed to do.
Table of Contents
- Installation
- Configuration
- Quick Start
- Function Quick Refrence
- Core Concepts
- API Reference
- Initialization
- Document Management
- Parsing
- Node Information
- Value Getters
- Navigation
- Object Lookup
- Array Access
- Path Queries (Dot Notation)
- Path Setters
- Node Creation
- Object Building
- Array Building
- Quick Build Helpers
- Serialization
- Deep Copy / Clone
- Merge
- Comparison
- Search
- Iteration
- Object Keys Extraction
- Path Manipulation
- Validation
- Statistics and Debug
- Type Conversion
- Cleanup
- Error Handling
- Macros
- Constants
- Complete Examples
- Example 1: Parse and Read
- Example 2: Build from Scratch
- Example 3: File I/O
- Example 4: Modify Existing JSON
- Example 5: Deep Nesting and Path Queries
- Example 6: Array Manipulation
- Example 7: Merge Two Objects
- Example 8: Clone and Compare
- Example 9: Search Functions
- Example 10: Iteration
- Example 11: Player Save/Load System
- Example 12: Server Configuration Loader
- Example 13: Validation and Error Handling
- Performance Tips
- Limitations
- Changelog
Installation
- Copy
json_parser.incinto yourpawno/include/directory. - Include it in your script:
#include <json_parser>
No plugins, no external dependencies. Pure Pawn.
Configuration
All limits can be overridden before including the file using #define:
| Define | Default | Description |
|---|---|---|
JSON_MAX_NODES | 2048 | Maximum number of JSON nodes across all documents |
JSON_MAX_KEY_LEN | 64 | Maximum length of a key string |
JSON_MAX_VALUE_LEN | 256 | Maximum length of a value string |
JSON_MAX_DEPTH | 32 | Maximum nesting depth during parsing |
JSON_MAX_DOCUMENTS | 16 | Maximum number of simultaneous documents |
JSON_MAX_STRING_LEN | 4096 | Maximum input JSON string length for parsing |
JSON_SERIALIZE_BUFFER | 4096 | Internal buffer size for serialization output |
Example override:
#define JSON_MAX_NODES 4096
#define JSON_MAX_STRING_LEN 8192
#include <json_parser>
Quick Start
Parsing JSON
new docId;
new jsonStr[] = "{\"name\":\"John\",\"age\":25,\"vip\":true}";
if (JSON_Parse(jsonStr, docId))
{
new root = JSON_GetRootNode(docId);
new name[32];
JSON_GetStringByPath(root, "name", name);
// name = "John"
new age;
JSON_GetIntByPath(root, "age", age);
// age = 25
new bool:vip;
JSON_GetBoolByPath(root, "vip", vip);
// vip = true
JSON_DestroyDocument(docId);
}
Building JSON
new docId, root;
root = JSON_BuildObject(docId);
JSON_ObjectSetString(root, "server", "My SA-MP Server");
JSON_ObjectSetInt(root, "maxPlayers", 100);
JSON_ObjectSetBool(root, "active", true);
new output[512];
JSON_Prettify(root, output);
print(output);
JSON_DestroyDocument(docId);
Output:
{
"server": "My SA-MP Server",
"maxPlayers": 100,
"active": true
}
Function Quick Reference
| Function | Returns | Description |
|---|---|---|
JSON_Init() | 1 | Initialize parser state |
JSON_Cleanup() | 1 | Free all documents and reset state |
JSON_CreateDocument() | docId | Create empty document |
JSON_DestroyDocument(docId) | 0/1 | Destroy document and free nodes |
JSON_GetRootNode(docId) | nodeId | Get root node of document |
JSON_Parse(str, &docId) | 0/1 | Parse JSON string |
JSON_ParseFile(file, &docId) | 0/1 | Parse JSON file |
JSON_Validate(str) | bool | Check if string is valid JSON |
JSON_GetErrorMessage(dest) | - | Get last parse error |
JSON_GetNodeType(nodeId) | type | Get node type constant |
JSON_GetNodeTypeName(nodeId, dest) | 0/1 | Get type as string |
JSON_GetNodeKey(nodeId, dest) | 0/1 | Get node key |
JSON_GetChildCount(nodeId) | count | Count direct children |
JSON_IsNull(nodeId) | bool | Check if null |
JSON_IsString(nodeId) | bool | Check if string |
JSON_IsInt(nodeId) | bool | Check if integer |
JSON_IsFloat(nodeId) | bool | Check if float |
JSON_IsBool(nodeId) | bool | Check if boolean |
JSON_IsObject(nodeId) | bool | Check if object |
JSON_IsArray(nodeId) | bool | Check if array |
JSON_IsNumber(nodeId) | bool | Check if int or float |
JSON_GetString(nodeId, dest) | 0/1 | Get string value |
JSON_GetInt(nodeId, &val) | 0/1 | Get integer value |
JSON_GetFloat(nodeId, &val) | 0/1 | Get float value |
JSON_GetBool(nodeId, &val) | 0/1 | Get boolean value |
JSON_GetParent(nodeId) | nodeId | Get parent node |
JSON_GetFirstChild(nodeId) | nodeId | Get first child |
JSON_GetLastChild(nodeId) | nodeId | Get last child |
JSON_GetNextSibling(nodeId) | nodeId | Get next sibling |
JSON_GetPrevSibling(nodeId) | nodeId | Get previous sibling |
JSON_GetObjectChild(nodeId, key) | nodeId | Find child by key |
JSON_ObjectHasKey(nodeId, key) | bool | Check if key exists |
JSON_GetArrayElement(nodeId, idx) | nodeId | Get array element by index |
JSON_GetArraySize(nodeId) | count | Get array length |
JSON_GetByPath(nodeId, path) | nodeId | Navigate by dot path |
JSON_GetStringByPath(nodeId, path, dest) | 0/1 | Get string by path |
JSON_GetIntByPath(nodeId, path, &val) | 0/1 | Get int by path |
JSON_GetFloatByPath(nodeId, path, &val) | 0/1 | Get float by path |
JSON_GetBoolByPath(nodeId, path, &val) | 0/1 | Get bool by path |
JSON_SetByPath(docId, nodeId, path, val) | 0/1 | Set node by path |
JSON_SetStringByPath(docId, nodeId, path, val) | 0/1 | Set string by path |
JSON_SetIntByPath(docId, nodeId, path, val) | 0/1 | Set int by path |
JSON_SetFloatByPath(docId, nodeId, path, val) | 0/1 | Set float by path |
JSON_SetBoolByPath(docId, nodeId, path, val) | 0/1 | Set bool by path |
JSON_RemoveByPath(nodeId, path) | 0/1 | Remove node by path |
JSON_EnsurePath(docId, nodeId, path) | nodeId | Create intermediate path nodes |
JSON_CreateObject(docId) | nodeId | Create empty object node |
JSON_CreateArray(docId) | nodeId | Create empty array node |
JSON_CreateString(docId, val) | nodeId | Create string node |
JSON_CreateInt(docId, val) | nodeId | Create integer node |
JSON_CreateFloat(docId, val) | nodeId | Create float node |
JSON_CreateBool(docId, val) | nodeId | Create boolean node |
JSON_CreateNull(docId) | nodeId | Create null node |
JSON_ObjectSetValue(nodeId, key, valNode) | 0/1 | Set key-value on object |
JSON_ObjectSetString(nodeId, key, val) | 0/1 | Set string on object |
JSON_ObjectSetInt(nodeId, key, val) | 0/1 | Set int on object |
JSON_ObjectSetFloat(nodeId, key, val) | 0/1 | Set float on object |
JSON_ObjectSetBool(nodeId, key, val) | 0/1 | Set bool on object |
JSON_ObjectSetNull(nodeId, key) | 0/1 | Set null on object |
JSON_ObjectRemoveKey(nodeId, key) | 0/1 | Remove key from object |
JSON_ArrayAppend(nodeId, valNode) | 0/1 | Append to array |
JSON_ArrayAppendString(nodeId, docId, val) | 0/1 | Append string to array |
JSON_ArrayAppendInt(nodeId, docId, val) | 0/1 | Append int to array |
JSON_ArrayAppendFloat(nodeId, docId, val) | 0/1 | Append float to array |
JSON_ArrayAppendBool(nodeId, docId, val) | 0/1 | Append bool to array |
JSON_ArrayInsert(nodeId, idx, valNode) | 0/1 | Insert into array |
JSON_ArrayRemove(nodeId, idx) | 0/1 | Remove from array |
JSON_BuildObject(&docId) | nodeId | Create doc with root object |
JSON_BuildArray(&docId) | nodeId | Create doc with root array |
JSON_Serialize(nodeId, dest, maxlen, pretty) | 0/1 | Serialize to string |
JSON_Minify(nodeId, dest) | 0/1 | Compact serialization |
JSON_Prettify(nodeId, dest) | 0/1 | Pretty serialization |
JSON_SerializeToFile(nodeId, file, pretty) | 0/1 | Serialize to file |
JSON_SerializeDoc(docId, dest, maxlen, pretty) | 0/1 | Serialize document |
JSON_SaveDocument(docId, file, pretty) | 0/1 | Save document to file |
JSON_CloneNode(docId, nodeId) | nodeId | Deep copy a node |
JSON_MergeObjects(docId, target, source, overwrite) | 0/1 | Merge two objects |
JSON_Equal(nodeA, nodeB) | bool | Deep equality check |
JSON_FindByKey(nodeId, key) | nodeId | Search by key recursively |
JSON_FindByStringValue(nodeId, val) | nodeId | Search by string value |
JSON_FindByIntValue(nodeId, val) | nodeId | Search by int value |
JSON_IterateObject(nodeId, prev) | nodeId | Manual object iteration |
JSON_IterateArray(nodeId, prev) | nodeId | Manual array iteration |
JSON_GetObjectKeys(nodeId, keys, max, maxlen) | count | Extract all keys |
JSON_NodeToString(nodeId, dest) | 0/1 | Convert any value to string |
JSON_NodeToInt(nodeId, &val) | 0/1 | Convert any value to int |
JSON_NodeToFloat(nodeId, &val) | 0/1 | Convert any value to float |
JSON_CountNodes(nodeId) | count | Count all nodes in subtree |
JSON_GetMaxDepth(nodeId) | depth | Get max nesting depth |
JSON_GetFreeNodeCount() | count | Get available node slots |
JSON_DebugPrintNode(nodeId, depth) | - | Print debug tree to console |
Core Concepts
Documents
A document is a container that owns a set of nodes. Every parsing or building operation starts with a document. Documents are identified by an integer ID.
- Maximum simultaneous documents:
JSON_MAX_DOCUMENTS(default 16) - Always destroy documents when done to free nodes
Nodes
Every JSON value (string, number, object, array, bool, null) is stored as a node. Nodes form a tree structure with parent-child and sibling relationships.
Each node has:
- A type (object, array, string, int, float, bool, null)
- A key (if it's a child of an object)
- A value (for primitive types)
- Links to parent, first child, last child, previous sibling, next sibling
Data Types
| Constant | Value | Description |
|---|---|---|
JSON_TYPE_NULL | 0 | JSON null |
JSON_TYPE_STRING | 1 | String value |
JSON_TYPE_INT | 2 | Integer value |
JSON_TYPE_FLOAT | 3 | Float value |
JSON_TYPE_BOOL | 4 | Boolean (true/false) |
JSON_TYPE_OBJECT | 5 | JSON object {} |
JSON_TYPE_ARRAY | 6 | JSON array [] |
API Reference
Initialization
JSON_Init()
Initializes the parser state. Called automatically by most functions. Safe to call multiple times.
JSON_Init();
Returns: 1 always.
Document Management
JSON_CreateDocument()
Creates a new empty document.
new docId = JSON_CreateDocument();
if (docId == JSON_INVALID_DOCUMENT)
{
print("ERROR: No free document slots!");
}
Returns: Document ID on success, JSON_INVALID_DOCUMENT (-1) on failure.
JSON_DestroyDocument(docId)
Destroys a document and frees all its nodes.
JSON_DestroyDocument(docId);
Returns: 1 on success, 0 on failure.
Always call this when you're done with a document to prevent node leaks.
JSON_GetRootNode(docId)
Gets the root node of a document.
new root = JSON_GetRootNode(docId);
if (root == JSON_INVALID_NODE)
{
print("Document has no root node");
}
Returns: Node ID or JSON_INVALID_NODE (-1).
Parsing
JSON_Parse(const jsonString[], &docId)
Parses a JSON string into a new document.
new docId;
new input[] = "{\"key\":\"value\",\"num\":42}";
if (JSON_Parse(input, docId))
{
new root = JSON_GetRootNode(docId);
// ... use the data ...
JSON_DestroyDocument(docId);
}
else
{
new errMsg[128];
JSON_GetErrorMessage(errMsg);
printf("Parse error: %s", errMsg);
}
Returns: 1 on success, 0 on failure.
Supported JSON features:
- Objects, arrays, strings, integers, floats, booleans, null
- Nested structures to
JSON_MAX_DEPTHlevels - Escape sequences in strings:
\",\\,\/,\b,\f,\n,\r,\t - Negative numbers and decimal floats
JSON_ParseFile(const filename[], &docId)
Reads a file and parses its contents as JSON.
new docId;
if (JSON_ParseFile("scriptfiles/config.json", docId))
{
new root = JSON_GetRootNode(docId);
// ...
JSON_DestroyDocument(docId);
}
Returns: 1 on success, 0 on failure.
Node Information
JSON_GetNodeType(nodeId)
Returns the type constant of a node.
new type = JSON_GetNodeType(nodeId);
if (type == JSON_TYPE_STRING)
{
// handle string
}
Returns: One of JSON_TYPE_* constants, or -1 if invalid.
JSON_GetNodeTypeName(nodeId, dest[], maxlen = sizeof(dest))
Gets a human-readable type name.
new typeName[16];
JSON_GetNodeTypeName(nodeId, typeName);
printf("Type: %s", typeName);
// Output: "string", "int", "float", "bool", "null", "object", "array", or "unknown"
Returns: 1 on success, 0 on failure.
JSON_GetNodeKey(nodeId, dest[], maxlen = sizeof(dest))
Gets the key of a node (only meaningful for children of objects).
new key[64];
JSON_GetNodeKey(childNode, key);
printf("Key: %s", key);
Returns: 1 on success, 0 on failure.
JSON_GetChildCount(nodeId)
Returns the number of direct children of a node.
new count = JSON_GetChildCount(objectNode);
printf("Object has %d properties", count);
Returns: Child count, or 0 if invalid/no children.
Type Check Functions
All return bool:
JSON_IsNull(nodeId) // true if JSON_TYPE_NULL
JSON_IsString(nodeId) // true if JSON_TYPE_STRING
JSON_IsInt(nodeId) // true if JSON_TYPE_INT
JSON_IsFloat(nodeId) // true if JSON_TYPE_FLOAT
JSON_IsBool(nodeId) // true if JSON_TYPE_BOOL
JSON_IsObject(nodeId) // true if JSON_TYPE_OBJECT
JSON_IsArray(nodeId) // true if JSON_TYPE_ARRAY
JSON_IsNumber(nodeId) // true if JSON_TYPE_INT or JSON_TYPE_FLOAT
Example:
if (JSON_IsString(node))
{
new val[128];
JSON_GetString(node, val);
printf("String value: %s", val);
}
else if (JSON_IsInt(node))
{
new val;
JSON_GetInt(node, val);
printf("Int value: %d", val);
}
Value Getters
JSON_GetString(nodeId, dest[], maxlen = sizeof(dest))
Gets the string value of a node.
new value[128];
if (JSON_GetString(node, value))
{
printf("Value: %s", value);
}
Returns: 1 on success, 0 on failure. Works on JSON_TYPE_STRING nodes.
JSON_GetInt(nodeId, &value)
Gets the integer value of a node.
new value;
if (JSON_GetInt(node, value))
{
printf("Value: %d", value);
}
Returns: 1 on success, 0 on failure. Works on JSON_TYPE_INT nodes.
JSON_GetFloat(nodeId, &Float:value)
Gets the float value of a node.
new Float:value;
if (JSON_GetFloat(node, value))
{
printf("Value: %f", value);
}
Returns: 1 on success, 0 on failure. Works on JSON_TYPE_FLOAT nodes.
JSON_GetBool(nodeId, &bool:value)
Gets the boolean value of a node.
new bool:value;
if (JSON_GetBool(node, value))
{
printf("Value: %s", value ? "true" : "false");
}
Returns: 1 on success, 0 on failure. Works on JSON_TYPE_BOOL nodes.
Navigation
These functions let you traverse the node tree manually.
JSON_GetParent(nodeId)
new parent = JSON_GetParent(childNode);
Returns: Parent node ID, or JSON_INVALID_NODE.
JSON_GetFirstChild(nodeId)
new first = JSON_GetFirstChild(objectNode);
Returns: First child node ID, or JSON_INVALID_NODE.
JSON_GetLastChild(nodeId)
new last = JSON_GetLastChild(objectNode);
Returns: Last child node ID, or JSON_INVALID_NODE.
JSON_GetNextSibling(nodeId)
new next = JSON_GetNextSibling(currentNode);
Returns: Next sibling node ID, or JSON_INVALID_NODE.
JSON_GetPrevSibling(nodeId)
new prev = JSON_GetPrevSibling(currentNode);
Returns: Previous sibling node ID, or JSON_INVALID_NODE.
Object Lookup
JSON_GetObjectChild(objectNode, const key[])
Finds a direct child of an object by key name.
new nameNode = JSON_GetObjectChild(root, "name");
if (nameNode != JSON_INVALID_NODE)
{
new name[32];
JSON_GetString(nameNode, name);
}
Returns: Node ID or JSON_INVALID_NODE.
JSON_ObjectHasKey(objectNode, const key[])
Checks if an object contains a specific key.
if (JSON_ObjectHasKey(root, "email"))
{
// key exists
}
Returns: bool.
Array Access
JSON_GetArrayElement(arrayNode, index)
Gets an array element by zero-based index.
new elem = JSON_GetArrayElement(arrayNode, 0); // first element
if (elem != JSON_INVALID_NODE)
{
new val;
JSON_GetInt(elem, val);
}
Returns: Node ID or JSON_INVALID_NODE.
JSON_GetArraySize(arrayNode)
Returns the number of elements in an array.
new size = JSON_GetArraySize(arrayNode
json-parseropenmp-libraryopenmp-serveropenmultiplayerpawnsa-mpsa-mp-librarysamp
Esta página se genera con lo que GitHub publica sobre el repositorio. samp.directory no aloja el código. Informar de un problema con esta ficha