json library i made quickly for geode. preserves insertion order for objects
- this was made to be easy to compile
- numbers are internally stored as double
- not made to handle extremely nested objects
#include <matjson.hpp>
auto object = matjson::parse(R"(
{
"hello": "world",
"foo": {
"bar": 2000
}
}
)");
object["hello"].as_string(); // world
object["foo"]["bar"].as_int(); // 2000
object.is_object(); // true
object.is_string(); // false
For the sake of simplicity, the library can only parse from a string, so you will have to load the whole file in memory yourself.
std::string file_contents = ...
auto object = matjson::parse(file_contents);
The library can also only directly output a string.
matjson::Value object = ...
std::string file_contents = object.dump();
write_to_file("epic.json", file_contents);
Value::dump
can also control indentation, see Dumping to string
There are many different ways to access inner values, depending on your needs:
auto object = matjson::parse(R"(
{
"hello": "world",
"foo": {
"bar": 2000
"numbers": [123, false, "not a number actually"]
}
}
)");
object["hello"].as_string(); // "world"
object["hello"].as<std::string>(); // "world"
object.get<std::string>("hello"); // "world"
object["foo"]["bar"].as_int(); // 2000
object["foo"]["bar"].as<int>(); // 2000
object["foo"].get<int>("bar"); // 2000
object["foo"]["numbers"][0].as_int(); // 123
object["foo"]["numbers"][0].as<int>(); // 123
object["foo"]["numbers"].get<int>(0); // 123
object.try_get("foo"); // std::optional<matjson::Value>(...)
object.try_get("sup"); // std::nullopt
object.contains("sup"); // false
// will insert "sup" into object as long as its not const.
// behaves like std::map::operator[]
object["sup"];
object["nya"] = 123;
object["hello"].is_string(); // true
object["hello"].is<std::string>(); // true
It is possible to (de)serialize your own types into json, by specializing matjson::Serialize<T>
.
struct User {
std::string name;
int age;
}
template <>
struct matjson::Serialize<User> {
static User from_json(const matjson::Value& value) {
return User {
.name = value["name"].as_string(),
.age = value["age"].as_int(),
};
}
static matjson::Value to_json(const User& user) {
return matjson::Object {
{ "name", user.name },
{ "age", user.age }
};
}
// You can also implement this method:
// > static bool is_json(const matjson::Value& value);
// It is only used if you do value.is<User>();
};
int main() {
User user = { "mat", 123 };
// gets implicitly converted into json
matjson::Value value = user;
value.dump(matjson::NO_INDENTATION); // {"name":"mat","age":123}
value["name"] = "hello";
// you have to use the templated methods for accessing custom types!
// it will *not* implicitly convert to User
User user2 = value.as<User>();
user2.name; // "hello"
}
To save a json value to a file or to pretty print it you can use the matjson::Value::dump
method.
// from the previous section
matjson::Value value = User { "mat", 123 };
// by default dumps with 4 spaces
value.dump();
// {
// "name": "mat",
// "age": 123
// }
value.dump(1); // 1 space indentation
// {
// "name": "mat",
// "age": 123
// }
// will create a compact json with no extra whitepace
value.dump(matjson::NO_INDENTATION);
value.dump(0); // same as above
// {"name":"mat","age":123}
value.dump(matjson::TAB_INDENTATION); // will indent with tabs
// like imagine '{\n\t"name": "mat",\n\t"age": 123\n}'
// default constructs to a json object, for convenience
matjson::Value value;
// null is nullptr
value["hello"] = nullptr;
value["hello"].is_null(); // true
just look at the main header for other things its not that hard to read the code