nlohmann/json
Library
nlohmann/json
Overview
nlohmann/json is the most popular JSON library designed for modern C++. It aims to treat JSON data as a first-class citizen in C++, providing an intuitive API and rich functionality. Usable by including a single header file, it allows JSON manipulation with an STL-like feel. With its focus on type safety and ease of use, it has become the de facto standard for JSON processing in C++ projects.
Details
nlohmann/json is a header-only JSON library developed leveraging C++11 and later features. It supports all JSON features (objects, arrays, strings, numbers, booleans, null) and provides advanced functionality such as automatic type inference, custom type serialization, SAX/DOM-style parsing, JSON pointers, and JSON patches. The design philosophy is "ease of use first," providing an interface that C++ programmers can use intuitively.
Key Features
- Header-only: Complete in a single file, no build configuration required
- STL-like: Intuitive operation similar to vector or map
- Type safety: Deep integration with C++ type system
- Rich functionality: JSON pointer, JSON patch, MessagePack/CBOR/UBJSON support
- Customizable: Automatic serialization for user-defined types
- Exception safe: Provides strong exception guarantees
Advantages and Disadvantages
Advantages
- Extremely intuitive and easy-to-use API design
- Easy to integrate with single header file
- Rich documentation and community support
- Automatic serialization for custom types
- Full UTF-8 support for internationalization
- Active development and maintenance
Disadvantages
- Performance lags behind other C++ JSON libraries
- Large file size (approximately 1MB)
- May increase compilation time
- Requires C++11 or later
- Relatively high memory usage
- Not suitable for processing huge JSON files
References
Code Examples
Basic Usage
#include <nlohmann/json.hpp>
#include <iostream>
using json = nlohmann::json;
int main() {
// Creating JSON object
json j = {
{"name", "John Doe"},
{"age", 30},
{"city", "Tokyo"},
{"is_active", true},
{"scores", {85, 90, 78}}
};
// Serialization (pretty print)
std::cout << j.dump(4) << std::endl;
// Element access
std::string name = j["name"];
int age = j["age"].get<int>();
return 0;
}
Parsing and Error Handling
#include <nlohmann/json.hpp>
#include <fstream>
using json = nlohmann::json;
void parseJsonFile(const std::string& filename) {
try {
// Read from file
std::ifstream file(filename);
json j;
file >> j;
// Safe element access
if (j.contains("users")) {
for (auto& user : j["users"]) {
std::cout << user.at("name") << std::endl;
}
}
} catch (json::parse_error& e) {
std::cerr << "Parse error: " << e.what() << std::endl;
} catch (json::out_of_range& e) {
std::cerr << "Key not found: " << e.what() << std::endl;
}
}
Custom Type Serialization
#include <nlohmann/json.hpp>
struct Person {
std::string name;
int age;
std::string email;
};
// Automatic serialization using macro
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Person, name, age, email)
int main() {
// Using custom type
Person p{"Alice", 25, "[email protected]"};
// Automatically convert to JSON
json j = p;
std::cout << j.dump(2) << std::endl;
// From JSON to custom type
json j2 = {{"name", "Bob"}, {"age", 30}, {"email", "[email protected]"}};
Person p2 = j2.get<Person>();
return 0;
}
Advanced Features
#include <nlohmann/json.hpp>
using json = nlohmann::json;
void advancedFeatures() {
json j = {
{"users", {
{{"name", "John"}, {"age", 30}},
{{"name", "Jane"}, {"age", 25}}
}}
};
// JSON pointer
auto name = j[json::json_pointer("/users/0/name")];
// JSON patch
json patch = {{
{"op", "replace"},
{"path", "/users/0/age"},
{"value", 31}
}};
j = j.patch(patch);
// Iteration
for (auto& [key, value] : j.items()) {
std::cout << key << ": " << value << std::endl;
}
// MessagePack conversion
std::vector<uint8_t> msgpack = json::to_msgpack(j);
json j_from_msgpack = json::from_msgpack(msgpack);
}
SAX-style Parsing
#include <nlohmann/json.hpp>
class MySaxHandler {
public:
bool null() { return true; }
bool boolean(bool val) { return true; }
bool number_integer(int64_t val) { return true; }
bool number_unsigned(uint64_t val) { return true; }
bool number_float(double val, const std::string& s) { return true; }
bool string(std::string& val) { return true; }
bool start_object(std::size_t elements) { return true; }
bool end_object() { return true; }
bool start_array(std::size_t elements) { return true; }
bool end_array() { return true; }
bool key(std::string& val) { return true; }
bool parse_error(std::size_t position, const std::string& last_token) { return false; }
};
void saxParsing() {
std::string json_str = R"({"name": "John", "age": 30})";
MySaxHandler handler;
json::sax_parse(json_str, &handler);
}
Configuration File Read/Write
#include <nlohmann/json.hpp>
#include <fstream>
class Config {
json config_;
std::string filename_;
public:
Config(const std::string& filename) : filename_(filename) {
load();
}
void load() {
try {
std::ifstream file(filename_);
if (file.is_open()) {
file >> config_;
}
} catch (...) {
config_ = json::object();
}
}
void save() {
std::ofstream file(filename_);
file << config_.dump(4);
}
template<typename T>
T get(const std::string& key, const T& default_value) {
return config_.value(key, default_value);
}
template<typename T>
void set(const std::string& key, const T& value) {
config_[key] = value;
}
};