Serialization - GitMasterNikanjam/nlohmann_json_examples GitHub Wiki
JSON serialization refers to the process of converting data structures (such as C++ objects, arrays, maps, etc.) into a JSON string format that can be stored, transferred, or shared. Deserialization is the reverse process—converting a JSON string back into a usable data structure in C++.
The nlohmann/json library makes it very easy to serialize and deserialize data in C++ to and from JSON. Let's break down serialization in more detail.
In nlohmann/json, you can serialize a variety of basic data types (like integers, strings, booleans, arrays, and objects) directly into JSON format.
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main() {
// Creating a JSON object
json j;
j["name"] = "Alice";
j["age"] = 25;
j["is_student"] = true;
j["skills"] = {"C++", "Python", "JavaScript"};
// Serialize JSON object to string
std::string serialized = j.dump();
std::cout << "Serialized JSON: " << serialized << std::endl;
return 0;
}
Serialized JSON: {"age":25,"is_student":true,"name":"Alice","skills":["C++","Python","JavaScript"]}
In the example above, the dump()
method converts the JSON object into a serialized JSON string.
By default, the serialized string is compact, but you can also pretty-print (format) the output using the dump()
method with indentation:
std::string pretty = j.dump(4); // 4 spaces indentation
std::cout << "Pretty-printed JSON:\n" << pretty << std::endl;
Pretty-printed JSON:
{
"age": 25,
"is_student": true,
"name": "Alice",
"skills": [
"C++",
"Python",
"JavaScript"
]
}
You can serialize more complex data structures that contain nested objects or arrays. For example:
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main() {
// Nested JSON object
json j;
j["person"] = {
{"name", "Bob"},
{"age", 30},
{"is_student", false}
};
j["person"]["skills"] = {"C++", "Python"};
// Serialize the complex JSON object
std::string serialized = j.dump(4);
std::cout << "Serialized JSON:\n" << serialized << std::endl;
return 0;
}
{
"person": {
"age": 30,
"is_student": false,
"name": "Bob",
"skills": [
"C++",
"Python"
]
}
}
To store serialized JSON data into a file, you can write the string result of dump()
into a file stream.
#include <iostream>
#include <fstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main() {
json j;
j["name"] = "Alice";
j["age"] = 25;
j["is_student"] = true;
// Serialize and write to file
std::ofstream file("output.json");
file << j.dump(4); // Pretty-print with 4-space indentation
file.close();
std::cout << "JSON written to file!" << std::endl;
return 0;
}
This will create an output.json
file with the serialized JSON content.
To serialize and deserialize custom C++ types, you need to implement special to_json
and from_json
functions. This allows you to convert your own classes and structures to and from JSON.
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
class Person {
public:
std::string name;
int age;
bool is_student;
Person(std::string n, int a, bool s) : name(n), age(a), is_student(s) {}
};
You need to define two functions for converting between your class and JSON:
// Convert from Person object to JSON
void to_json(json& j, const Person& p) {
j = json{{"name", p.name}, {"age", p.age}, {"is_student", p.is_student}};
}
// Convert from JSON to Person object
void from_json(const json
```cpp
& j, Person& p) {
j.at("name").get_to(p.name);
j.at("age").get_to(p.age);
j.at("is_student").get_to(p.is_student);
}
Now, you can easily serialize and deserialize objects of your custom class using the nlohmann::json
library:
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
class Person {
public:
std::string name;
int age;
bool is_student;
Person(std::string n, int a, bool s) : name(n), age(a), is_student(s) {}
};
// Define the to_json and from_json functions
void to_json(json& j, const Person& p) {
j = json{{"name", p.name}, {"age", p.age}, {"is_student", p.is_student}};
}
void from_json(const json& j, Person& p) {
j.at("name").get_to(p.name);
j.at("age").get_to(p.age);
j.at("is_student").get_to(p.is_student);
}
int main() {
// Create a Person object
Person alice("Alice", 25, true);
// Serialize the Person object to JSON
json j = alice;
std::cout << "Serialized JSON:\n" << j.dump(4) << std::endl;
// Deserialize the JSON back to a Person object
Person new_person = j.get<Person>();
std::cout << "\nDeserialized Person:\n";
std::cout << "Name: " << new_person.name << "\n";
std::cout << "Age: " << new_person.age << "\n";
std::cout << "Is Student: " << std::boolalpha << new_person.is_student << std::endl;
return 0;
}
Serialized JSON:
{
"age": 25,
"is_student": true,
"name": "Alice"
}
Deserialized Person:
Name: Alice
Age: 25
Is Student: true
For more complex objects, such as those containing nested objects, arrays, or other custom types, the to_json
and from_json
functions can be expanded to handle these cases. For example, if Person
had a list of skills:
class Person {
public:
std::string name;
int age;
bool is_student;
std::vector<std::string> skills;
Person(std::string n, int a, bool s, std::vector<std::string> sk)
: name(n), age(a), is_student(s), skills(sk) {}
};
void to_json(json& j, const Person& p) {
j = json{{"name", p.name}, {"age", p.age}, {"is_student", p.is_student}, {"skills", p.skills}};
}
void from_json(const json& j, Person& p) {
j.at("name").get_to(p.name);
j.at("age").get_to(p.age);
j.at("is_student").get_to(p.is_student);
j.at("skills").get_to(p.skills);
}
While JSON serialization is flexible and human-readable, it's slower than binary formats. If performance is a priority (e.g., for high-frequency data exchanges), consider more compact formats such as MessagePack or Protocol Buffers. However, for most general purposes where JSON is favored for its readability, nlohmann/json offers a good balance between ease of use and performance.
-
Serialization with nlohmann/json is straightforward: you use
dump()
to convert objects into JSON strings. - You can pretty-print JSON with indentation by passing an argument to
dump()
. -
Custom classes require implementing
to_json
andfrom_json
functions, enabling seamless integration with JSON serialization and deserialization. - The library provides a flexible and powerful toolset for both simple and complex serialization needs, making it a popular choice for C++ projects dealing with JSON.