acedia-cookbook/src/collections/using_json.md
2022-08-12 01:44:17 +07:00

3.6 KiB

Using JSON data

JSON data can be stored inside Acedia's collections using only built-in values types and ArrayList/HashTable collections:

  • JSON's null can be stored as none;
  • JSON's true/false can be stored as bool'
  • JSON's number can be stored as either int or float (actually Acedia also contains BigInt type for storing arbitrarily large integer values, but it isn't yet implemented into JSON parsing);
  • JSON's string can be stored as string/Text/MutableText;
  • JSON's array can be stored as an ArrayList;
  • JSON's object can be stored as HashTable with Text keys.

NOTE: JSON does not have a separate undefined type and Acedia uses none instead of the missing values.

Converting JSON into Acedia collections

Parsing JSON input

To get an Acedia collection from a JSON object like this one:

{
    "innerObject": {
        "my_bool": true,
        "array": [
            "Engine.Actor",
            false,
            null,
            {
            "something \"here\"": "yes",
            "maybe": 0.003
            },
            56.6
        ],
        "one more": {
            "nope": 324532,
            "whatever": false,
            "o rly?": "ya rly"
        },
        "my_int": -9823452
    },
    "some_var": -7.32,
    "another_var": "aye!"
}

recorded in the string named jsonData you can do the following:

local Parser parser;
local HashTable jsonObject;

parser = _.text.ParseString(jsonData);
jsonObject = HashTable(_.json.ParseWith(parser));
if (!parser.Ok()) {
    // Handle errors
}
else if (!parser.Skip().HasFinished()) {
    // There is more input left after parsing JSON value - is this a problem?
}
// '/innerObject/array/3/maybe' is  0.003
Log("'/innerObject/array/3/maybe' is"
    @ jsonObject.GetFloatBy(P("/innerObject/array/3/maybe")));

Constructing by hand

Example of constructing the same object by hand:

local HashTable jsonObject;
local HashTable innerObject, oneMore, anonymousObject;
local ArrayList jsonArray;

anonymousObject = _.collections.EmptyHashTable();
anonymousObject.SetString(P("something \"here\""), "yes");
anonymousObject.SetFloat(P("maybe"), 0.003);

jsonArray = _.collections.EmptyArrayList()
    .AddString("Engine.Actor")
    .jsonArray.AddBool(false)
    .jsonArray.AddItem(none)
    .jsonArray.AddItem(anonymousObject)
    .jsonArray.AddFloat(56.6);

oneMore = _.collections.EmptyHashTable()
    .SetString(P("o rly?"), "ya rly")
    .SetFloat(P("nope"), 324532)
    .SetBool(P("whatever"), false);

innerObject = _.collections.EmptyHashTable()
    .SetItem(P("array"), jsonArray)
    .SetItem(P("one more"), oneMore)
    .SetBool(P("my_bool"), true)
    .SetInt(P("my_int"), -9823452);

//  Put it all together!
jsonObject = _.collections.EmptyHashTable()
    .SetItem(P("innerObject"), innerObject)
    .SetFloat(P("some_var"), -7.32)
    .SetString(P("another_var"), "aye!");
//  If you only want to keep `jsonObject`, release other references -
//  they won't disappear
anonymousObject.FreeSelf();
jsonArray.FreeSelf();
oneMore.FreeSelf();
innerObject.FreeSelf();

Converting Acedia collections into JSON

Use _.json.Print() to get a compact JSON representation:

//  {"innerObject":{"my_bool":true,"array":["Engine.Actor",false,null,{"something \"here\"":"yes","maybe":0.003},56.6],"one more":{"nope":324532,"whatever":false,"o rly?":"ya rly"},"my_int":-9823452},"some_var":-7.32,"another_var":"aye!"}
Log(_.text.IntoString(_.json.Print(jsonObject)));

or _.json.PrettyPrint() for a nice-looking (multiline, indented and colored) result.