JSON Quick Start
This page introduces the fastest way to use the Vix JSON module in an application.
The goal is not to cover every helper in detail. The goal is to show the normal workflow: include the module, create JSON values, parse input, read fields safely, write JSON, and use the same helpers inside a Vix HTTP route.
For most application code, include:
#include <vix/json.hpp>Then use the JSON helpers from:
namespace vix::jsonCreate a JSON value
The main JSON type is Json.
#include <vix/json.hpp>
#include <vix/print.hpp>
using namespace vix::json;
int main()
{
Json app = {
{"name", "Vix.cpp"},
{"type", "runtime"},
{"stable", true}
};
vix::print(dumps_pretty(app));
return 0;
}Output shape:
{
"name": "Vix.cpp",
"type": "runtime",
"stable": true
}Json is an alias of nlohmann::json, so normal nlohmann::json syntax works.
Vix adds helpers for the patterns that appear often in application code.
Build objects and arrays
Use o() to build an object and a() to build an array.
#include <vix/json.hpp>
#include <vix/print.hpp>
using namespace vix::json;
int main()
{
Json user = o(
"id", 42,
"name", "Ada",
"active", true,
"skills", a("C++", "Networking", "Systems")
);
vix::print(dumps_pretty(user));
return 0;
}Output shape:
{
"id": 42,
"name": "Ada",
"active": true,
"skills": ["C++", "Networking", "Systems"]
}The o() helper expects alternating key/value arguments:
auto user = o("id", 42, "name", "Ada");This is easier to read in route responses, configuration generation, and tests.
Parse JSON from a string
Use loads() when invalid JSON should throw.
#include <vix/json.hpp>
#include <vix/print.hpp>
using namespace vix::json;
int main()
{
Json data = loads(R"({
"name": "Vix.cpp",
"version": "2.6",
"ok": true
})");
vix::print(dumps_pretty(data));
return 0;
}Use try_loads() when the input can be invalid.
#include <vix/json.hpp>
#include <vix/print.hpp>
using namespace vix::json;
int main()
{
auto data = try_loads(R"({"name":"Vix.cpp","ok":true})");
if (!data)
{
vix::print("Invalid JSON");
return 1;
}
vix::print(dumps_pretty(*data));
return 0;
}In real applications, try_loads() is usually the better choice for request bodies, user input, files from external systems, or anything that may be malformed.
Read fields safely
A JSON field can be missing or have the wrong type. Instead of checking every field manually, use get_or() or get_opt().
#include <vix/json.hpp>
#include <vix/print.hpp>
using namespace vix::json;
int main()
{
Json user = o(
"id", 42,
"name", "Ada"
);
int id = get_or<int>(user, "id", 0);
std::string name = get_or<std::string>(user, "name", "unknown");
std::string email = get_or<std::string>(user, "email", "none");
vix::print("id", id);
vix::print("name", name);
vix::print("email", email);
return 0;
}Output shape:
id 42
name Ada
email noneUse get_opt<T>() when the field is optional and you want to know whether it exists.
if (auto email = get_opt<std::string>(user, "email"))
{
vix::print("email", *email);
}
else
{
vix::print("email missing");
}Use ensure<T>() when the field is required.
std::string required_name = ensure<std::string>(user, "name");If the key is missing or the type is wrong, ensure<T>() throws.
Work with nested data
For nested JSON values, use jget() to read by path.
#include <vix/json.hpp>
#include <vix/print.hpp>
using namespace vix::json;
int main()
{
Json data = loads(R"({
"user": {
"name": "Ada",
"roles": ["admin", "editor"]
}
})");
const Json* name = jget(data, "user.name");
const Json* first_role = jget(data, "user.roles[0]");
if (name)
{
vix::print("name", name->get<std::string>());
}
if (first_role)
{
vix::print("role", first_role->get<std::string>());
}
return 0;
}Output shape:
name Ada
role adminUse jset() to write nested values.
jset(data, "user.profile.country", "UG");
jset(data, "user.roles[1]", "developer");After this, data contains the new nested fields.
Serialize JSON
Use dumps_pretty() when the output is meant to be read by a person.
std::string readable = dumps_pretty(data);Use dumps_compact() when the output is meant for a network response, compact storage, or single-line logs.
std::string compact = dumps_compact(data);Example:
#include <vix/json.hpp>
#include <vix/print.hpp>
using namespace vix::json;
int main()
{
Json event = o(
"type", "user.created",
"user_id", 42,
"ok", true
);
vix::print(dumps_compact(event));
return 0;
}Output:
{ "type": "user.created", "user_id": 42, "ok": true }Read and write JSON files
Use dump_file() to write a JSON document.
#include <vix/json.hpp>
using namespace vix::json;
int main()
{
Json config = o(
"app", "Vix.cpp",
"debug", true,
"port", 8080
);
dump_file("config/app.json", config);
return 0;
}Use load_file() when the file must exist and must be valid.
Json config = load_file("config/app.json");Use try_load_file() when the file is optional or may be invalid.
auto config = try_load_file("config/app.json");
if (!config)
{
return 1;
}Use JSON in a Vix HTTP route
The JSON helpers can be used directly inside Vix HTTP handlers.
#include <vix.hpp>
#include <vix/json.hpp>
using namespace vix;
int main()
{
App app;
app.post("/users", [](Request &req, Response &res) {
using namespace vix::json;
auto body = try_loads(req.body());
if (!body)
{
res.status(http::BAD_REQUEST).json({
"error", "Invalid JSON"
});
return;
}
const std::string name = get_or<std::string>(*body, "name", "");
if (name.empty())
{
res.status(http::UNPROCESSABLE_ENTITY).json({
"error", "Missing required field",
"field", "name"
});
return;
}
res.status(http::CREATED).json({
"ok", true,
"name", name
});
});
app.run();
return 0;
}Test the route:
curl -i \
-X POST http://127.0.0.1:8080/users \
-H "Content-Type: application/json" \
-d '{"name":"Ada"}'Expected response shape:
{
"ok": true,
"name": "Ada"
}Invalid JSON produces an error response:
curl -i \
-X POST http://127.0.0.1:8080/users \
-H "Content-Type: application/json" \
-d 'not-json'Expected response shape:
{
"error": "Invalid JSON"
}A complete quick-start example
This example combines the main pieces: building JSON, reading fields, writing nested values, and printing the final document.
#include <vix/json.hpp>
#include <vix/print.hpp>
using namespace vix::json;
int main()
{
Json user = o(
"id", 42,
"name", "Ada",
"roles", a("admin", "editor")
);
const std::string name = get_or<std::string>(user, "name", "unknown");
jset(user, "profile.country", "UG");
jset(user, "profile.display_name", name);
dump_file("user.json", user);
Json reloaded = load_file("user.json");
vix::print(dumps_pretty(reloaded));
return 0;
}Output shape:
{
"id": 42,
"name": "Ada",
"roles": ["admin", "editor"],
"profile": {
"country": "UG",
"display_name": "Ada"
}
}This is the normal JSON workflow in Vix: build a value, read what you need safely, update it when necessary, serialize it, and use the same approach in HTTP handlers or standalone tools.
Next steps
Continue with Build JSON to learn the object and array builders in more detail.