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

124 lines
3.6 KiB
Markdown

# 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:
```json
{
"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:
```unrealscript
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:
```unrealscript
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:
```unrealscript
// {"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.