JSON to C++: classes for nlohmann/json
C++ has no built-in JSON support, and the most popular library for it is nlohmann/json, a single-header library that converts between JSON and user types through from_json and to_json functions. This JSON to C++ generator produces both: classes that mirror your sample, and the conversion functions that let you write Task t = nlohmann::json::parse(text);.
Example
{
"id": 42,
"title": "Write docs",
"done": false,
"priority": 2.5,
"tags": ["docs"],
"owner": { "name": "Ada", "email": null },
"due": "2026-10-01T09:00:00Z",
"subtasks": [
{ "title": "Outline", "estimate": 2 },
{ "title": "Draft" }
]
}
The Subtask class, as generated:
class Subtask {
public:
Subtask() = default;
virtual ~Subtask() = default;
private:
std::string title;
std::optional<int64_t> estimate;
public:
const std::string & get_title() const { return title; }
std::string & get_mutable_title() { return title; }
void set_title(const std::string & value) { this->title = value; }
const std::optional<int64_t> & get_estimate() const { return estimate; }
std::optional<int64_t> & get_mutable_estimate() { return estimate; }
void set_estimate(const std::optional<int64_t> & value) { this->estimate = value; }
};
Each member has a const getter, a mutable getter and a setter. The optional estimate is std::optional<int64_t>, which requires C++17. Arrays become std::vector, and a value that is only null in the sample is kept as nlohmann::json so it can hold anything.
What full mode adds
- A
namespace quicktypewith helper functions for reading optional properties safely. adl_serializerspecializations innamespace nlohmannforstd::optionalandstd::shared_ptr.from_jsonandto_jsonfor every class, soj.get<Task>()andnlohmann::json j = task;work.- A header comment explaining how to include
json.hpp; the file uses#pragma onceand#include "json.hpp".
#include "Task.hpp"
auto task = nlohmann::json::parse(text).get<quicktype::Task>();
std::cout << task.get_title() << "\n";
Type mapping
| JSON | C++ |
|---|---|
| integer / decimal | int64_t / double |
| boolean / string | bool / std::string |
| array | std::vector<T> |
| object | a class |
| optional | std::optional<T> |
| null only / mixed | nlohmann::json or std::variant |
Dates stay std::string; convert them with std::chrono parsing or a date library where needed. Member names use snake_case, the common C++ style, while the conversion functions keep reading the original JSON keys.
Error handling
nlohmann/json reports mismatches with exceptions. Reading a required key that is missing throws nlohmann::json::out_of_range, and a value of the wrong type throws nlohmann::json::type_error; parsing invalid JSON throws parse_error. Wrap the get<Task>() call in a try block and log e.what(), which names the key or position involved. Optional members use std::optional, so an absent value simply leaves them empty instead of throwing.
Getting accurate types
The generator can only see your sample. If a number is always whole in the sample, it becomes int64_t, and a later 2.5 from the server fails to convert. Paste several records, including ones with decimals, nulls and missing keys, so the generated members use double and std::optional where needed.
Tips
- If you prefer plain aggregates, turn the classes into
structs with public members and use nlohmann'sNLOHMANN_DEFINE_TYPE_NON_INTRUSIVEmacro instead of handwritten functions. - Compile with
-std=c++17or newer because ofstd::optional. - Split the output into a header per class if your project prefers that layout.
- The file is header-only: it starts with
#pragma onceand defines its helpersinline, so you can save it asTask.hppand include it from several source files without link errors.
Format the generated code with the C++ Formatter. From XML? Use XML to C++. Check your input with the JSON Validator. Generation happens in your browser.