Json API
The AngelScript JSON API provides robust parsing and encoding of JSON directly into native AngelScript structures. JSON objects map to dictionary objects, using standard AngelScript types.
This API mirrors the Lua JSON API and is designed to behave identically where possible.
Overview
Available functions:
json_parse(text, result, error)
Parse JSON text into a dictionary
json_decode(text, result, error)
Alias of json_parse
json_stringify(value, json, error)
Convert a dictionary into a JSON string
json_encode(value, json, error)
Alias of json_stringify
All functions return true on success and false on failure, with detailed error messages.
JSON → Dictionary
bool json_parse(const string &in text, dictionary &out result, string &out error)
bool json_parse(const string &in text, dictionary &out result, string &out error)bool json_decode(const string &in text, dictionary &out result, string &out error)
bool json_decode(const string &in text, dictionary &out result, string &out error)Parses a JSON string and converts it into a nested AngelScript dictionary.
Parameters
text
string
JSON text to parse
result
dictionary
Output dictionary filled with parsed values
error
string
Error message if the function fails
JSON → AngelScript Type Mapping
Object {}
dictionary (recursively nested)
String "text"
string
Number 123, 4.5
double
Boolean true/false
double (1.0/0.0)
null
field omitted
Array [...]
(currently skipped)
Example
dictionary d;
string err;
bool ok = json_parse("{\"a\":1, \"b\":\"hello\"}", d, err);
if (!ok)
{
log_error("JSON parse failed: " + err);
return;
}
double a;
string b;
d.get("a", a); // 1.0
d.get("b", b); // "hello"Dictionary → JSON
bool json_stringify(const dictionary &in value, string &out json, string &out error)
bool json_stringify(const dictionary &in value, string &out json, string &out error)bool json_encode(const dictionary &in value, string &out json, string &out error)
bool json_encode(const dictionary &in value, string &out json, string &out error)Converts a dictionary (and any nested dictionaries) into valid JSON text.
Parameters
value
dictionary
The object to convert into JSON
json
string
Output JSON text
error
string
Error message if the function fails
AngelScript → JSON Type Mapping
double
number
string
string
bool
boolean
dictionary@
JSON object
null dictionary@
null
(any other type)
error
Example
dictionary d;
d.set("name", "Player1");
d.set("score", 120.0);
d.set("alive", true);
string json;
string err;
if (!json_stringify(d, json, err))
{
log_error("Stringify failed: " + err);
}
else
{
log("JSON: " + json);
}Output:
{"name":"Player1","score":120,"alive":true}Nesting Example
JSON objects automatically map to nested dictionaries:
string text = """
{
"player": {
"name": "Alice",
"pos": { "x": 10, "y": 20 }
}
}
""";
dictionary root;
string err;
json_parse(text, root, err);
dictionary@ player;
root.get("player", @player);
string name;
dictionary@ pos;
double px, py;
player.get("name", name);
player.get("pos", @pos);
pos.get("x", px);
pos.get("y", py);Null Behavior
JSON null becomes nonexistent key:
{"a":1,"b":null,"c":2}Becomes:
d.exists("a") == true
d.exists("b") == false
d.exists("c") == trueUnsupported Types
The AngelScript dictionary can technically store any type, but the JSON stringifier only supports:
doublestringbooldictionary@
Anything else causes:
json_stringify: unsupported value type in dictionaryArrays
JSON arrays ([ ... ]) are currently skipped.
If you need them, support can be added using array<T> or CScriptArray.
Full Roundtrip Example
dictionary d;
d.set("value", 123.0);
d.set("name", "Test");
d.set("ok", true);
dictionary inner;
inner.set("x", 10.0);
inner.set("y", 20.0);
d.set("pos", @inner);
string json, err;
json_stringify(d, json, err);
// parse it back
dictionary back;
json_parse(json, back, err);Full API Test
void DumpDict(const string &in label, dictionary &in d)
{
log(label);
array<string>@ keys = d.getKeys();
for (uint i = 0; i < keys.length(); i++)
{
string k = keys[i];
// Try double first
double dv;
string sv;
bool gotDouble = d.get(k, dv);
bool gotString = d.get(k, sv);
string vStr;
if (gotDouble)
vStr = "double " + k + " = " + dv;
else if (gotString)
vStr = "string " + k + " = \"" + sv + "\"";
else
vStr = "key " + k + " (unsupported type in dump)";
log(" " + vStr);
}
}
void TestBasicParse()
{
log("[1] Basic json_parse / json_decode");
const string jsonText = """
{
"number": 123,
"float": 3.14,
"bool_true": true,
"bool_false": false,
"text": "hello",
"object": { "x": 10, "y": 20 }
}
""";
dictionary d;
string err;
if (!json_parse(jsonText, d, err))
{
log_error(" [FAIL] json_parse failed: " + err);
return;
}
log(" [ OK ] json_parse succeeded");
DumpDict(" Dump of parsed dictionary:", d);
// Basic checks
double num = 0;
double flt = 0;
string txt;
if (d.get("number", num) && num == 123)
log(" [ OK ] number == 123");
else
log_error(" [FAIL] number != 123");
if (d.get("float", flt) && flt > 3.13 && flt < 3.15)
log(" [ OK ] float ~= 3.14");
else
log_error(" [FAIL] float ~= 3.14");
if (d.get("text", txt) && txt == "hello")
log(" [ OK ] text == \"hello\"");
else
log_error(" [FAIL] text != \"hello\"");
// bools are stored as doubles (1.0 / 0.0)
double bt = 0, bf = 1;
d.get("bool_true", bt);
d.get("bool_false", bf);
if (bt == 1.0 && bf == 0.0)
log(" [ OK ] bool_true/false mapped to 1.0/0.0");
else
log_error(" [FAIL] bool mapping incorrect");
// Test alias json_decode
dictionary d2;
string err2;
if (json_decode("{\"a\":1,\"b\":2}", d2, err2))
log(" [ OK ] json_decode succeeded");
else
log_error(" [FAIL] json_decode failed: " + err2);
}
void TestInvalidParse()
{
log("\n[2] Invalid JSON parse test");
dictionary d;
string err;
const string badJson = "{ invalid json !!! }";
bool ok = json_parse(badJson, d, err);
if (!ok)
{
log(" [ OK ] json_parse returned false for invalid JSON");
log(" error: " + err);
}
else
{
log_error(" [FAIL] json_parse unexpectedly succeeded on invalid JSON");
}
}
void TestStringifyRoundtrip()
{
log("\n[3] json_stringify / json_encode roundtrip");
dictionary d;
d.set("hello", "world");
d.set("num", 42.0); // numbers are stored as double
d.set("float", 1.5);
d.set("flag_bool", true); // bool (script side)
d.set("flag_num", 1.0); // numeric boolean
// nested object
dictionary nested;
nested.set("x", 10.0);
nested.set("y", 20.0);
d.set("nested", @nested);
DumpDict(" Original dictionary:", d);
string json;
string err;
if (!json_stringify(d, json, err))
{
log_error(" [FAIL] json_stringify failed: " + err);
return;
}
log(" [ OK ] json_stringify succeeded");
log(" JSON: " + json);
// Roundtrip: parse back
dictionary back;
string err2;
if (!json_parse(json, back, err2))
{
log_error(" [FAIL] parse(stringify(...)) failed: " + err2);
return;
}
log(" [ OK ] parse(stringify(...)) succeeded");
DumpDict(" Decoded dictionary:", back);
// Test alias json_encode
string json2, err3;
if (json_encode(d, json2, err3))
log(" [ OK ] json_encode succeeded: " + json2);
else
log_error(" [FAIL] json_encode failed: " + err3);
}
void TestNullAndArrays()
{
log("\n[4] Null and array handling note");
const string txt = """
{
"a": 1,
"b": null,
"c": [1,2,3]
}
""";
dictionary d;
string err;
if (!json_parse(txt, d, err))
{
log_error(" [FAIL] parse failed: " + err);
return;
}
DumpDict(" Parsed dictionary:", d);
// "b" is null -> omitted
double a = 0;
bool hasB = d.exists("b");
d.get("a", a);
if (a == 1.0 && !hasB)
log(" [ OK ] null field skipped, 'a' present");
else
log_error(" [FAIL] null or 'a' handling incorrect");
// "c" is an array -> currently skipped
if (!d.exists("c"))
log(" [ OK ] array key 'c' skipped as expected");
else
log_error(" [FAIL] array key 'c' unexpectedly present");
}
int main()
{
log("=== JSON API Test Begin (AngelScript) ===");
TestBasicParse();
TestInvalidParse();
TestStringifyRoundtrip();
TestNullAndArrays();
log("=== JSON API Test End ===");
return 0;
}
Summary of Functions
json_parse(text, result, error)
Parse JSON into dictionary
json_decode(text, result, error)
Alias of parse
json_stringify(value, json, error)
Convert dictionary to JSON
json_encode(value, json, error)
Alias of stringify
Last updated