Fading Coder

An Old Coder’s Final Dance

You are here: Home > Tech > Content

Using the nlohmann Open-Source JSON Library in C++: A Practical Guide

Tech 2

Introduction

In the past, JSON processing in C++ was often handled using Qt's QJsonDocument and associated classess. However, this approach tends to be verbose and less elegant. For a more convenient and intuitive solution, many developers now rely on the open-source libray nlohmann/json. Highly regarded worldwide, it offers concise methods for working with JSON data in C++ and has become the library of choice for numerous programmers.

Rather than referencing the exhaustive documentation available on its GitHub page, which can sometimes feel overwhelming and include seldom-used features, this article aims to sumarize the essential functionalities alongside examples, enabling new users to grasp the library quickly.


Project Setup

Although nlohmann/json includes CMake configuration files, you don't need to go through the CMake setup process for basic usage. Simply copy the contents of the include directory and add it to your project. With the header file included, you can start using the library as follows:

#include "nlohmann/json.hpp"
using json = nlohmann::json;

Core Features

1. Creating JSON Objects

You can construct JSON objects conveniently by assigning values to named keys:

json data;
data["pi"] = 3.1415;
data["happy"] = true;
data["name"] = "Niels";
data["nothing"] = nullptr;
data["nested_object"]["key"] = "value";
data["array"] = {1, 2, 3};
data["complex_obj"] = { {"currency", "USD"}, {"value", 99.99} };

Explicit type initialization is also available when needed:

json emptyArray = json::array();
json emptyObj = json::object();
json arrayWithData = json::array({ {"currency", "USD"}, {"value", 99.99} });

2. Creating JSON from STL Containers

nlohmann seamlessly integrates with standard STL containers:

std::vector<int> intVec = {1, 2, 3, 4};
json vecJson(intVec);

std::map<std::string, int> strIntMap = { {"one", 1}, {"two", 2} };
json mapJson(strIntMap);

Containers such as std::set, std::unordered_map, and std::array are also supported, preserving their corresponding behavior.

3. Serializing and Deserializing JSON

  • Deserialization: Convert a string directly into a JSON object.
json deserialized = "{ \"hello\": true }"_json;
  • Serialization: Convert a JSON object into a string.
std::string serialized = deserialized.dump();
std::cout << deserialized.dump(4) << std::endl; // Pretty formatting

4. File and Stream Usage

You can intuitively read from or write to local files:

// Deserialize from file
std::ifstream input("data.json");
json fileJson;
input >> fileJson;

// Serialize to file
std::ofstream output("formatted.json");
output << std::setw(4) << fileJson << std::endl;

5. Mapping JSON to Custom Data Types

You can convert between JSON objects and custom C++ structs by defining to_json and from_json functions:

struct Person {
    std::string name;
    int age;
};

void to_json(json& j, const Person& p) {
    j = json{{"name", p.name}, {"age", p.age}};
}

void from_json(const json& j, Person& p) {
    j.at("name").get_to(p.name);
    j.at("age").get_to(p.age);
}

// Usage
Person person = {"Alice", 30};
json jsonData = person;
Person extracted = jsonData.get<Person>();

6. Binary Conversion

nlohmann supports serialization into compact binary formats such as CBOR and MessagePack:

json sample = { {"compact", true}, {"version", 1} };
std::vector<uint8_t> cborData = json::to_cbor(sample);

To save binary-encoded data into a file:

std::ofstream output("binary.dat", std::ios::binary);
output.write(reinterpret_cast<const char*>(cborData.data()), cborData.size());

Practical Examples

Example 1: Parsing Simple JSON

#include "nlohmann/json.hpp"
#include <fstream>
using json = nlohmann::json;

int main() {
    std::ifstream input("simple.json");
    json j;
    input >> j;

    float pi = j.at("pi");
    bool happy = j.at("happy");
    return 0;
}

Example 2: Nested JSON Parsing

For a complex JSON structure with nested objects and arrays, define structs and write helper funcsions for parsing:

#include "nlohmann/json.hpp"
#include <fstream>
#include <string>

struct Track {
    std::string name;
    std::vector<std::string> files;
};

struct VideoSettings {
    int width;
    int height;
};

void to_json(json& j, const Track& t) {
    j = json{{"name", t.name}, {"files", t.files}};
}

int main() {
    std::ifstream input("complex.json");
    json parsedData;
    input >> parsedData;

    VideoSettings settings = parsedData["settings"].get<VideoSettings>();
    return 0;
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.