本文首发于个人博客https://kezunlin.me/post/f3c3eb8/,欢迎阅读最新内容!

tutorial to use nlohmann json for serializing data with modern cpp

Guide

include

#include <nlohmann/json.hpp>

// for convenience
using json = nlohmann::json;

compile with

-std=c++11

CMakeLists.txt

# CMakeLists.txt
find_package(nlohmann_json 3.2.0 REQUIRED)
...
add_library(foo ...)
...
target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)

Usage

json demo

{
"pi": 3.141,
"happy": true,
"name": "Niels",
"nothing": null,
"answer": {
"everything": 42
},
"list": [1, 0, 2],
"object": {
"currency": "USD",
"value": 42.99
}
}

with code

// create an empty structure (null)
json j; // add a number that is stored as double (note the implicit conversion of j to an object)
j["pi"] = 3.141; // add a Boolean that is stored as bool
j["happy"] = true; // add a string that is stored as std::string
j["name"] = "Niels"; // add another null object by passing nullptr
j["nothing"] = nullptr; // add an object inside the object
j["answer"]["everything"] = 42; // add an array that is stored as std::vector (using an initializer list)
j["list"] = { 1, 0, 2 }; // add another object (using an initializer list of pairs)
j["object"] = { {"currency", "USD"}, {"value", 42.99} }; // instead, you could also write (which looks very similar to the JSON above)
json j2 = {
{"pi", 3.141},
{"happy", true},
{"name", "Niels"},
{"nothing", nullptr},
{"answer", {
{"everything", 42}
}},
{"list", {1, 0, 2}},
{"object", {
{"currency", "USD"},
{"value", 42.99}
}}
};

serialization

// create object from string literal
json j = "{ \"happy\": true, \"pi\": 3.141 }"_json; // or even nicer with a raw string literal
auto j2 = R"(
{
"happy": true,
"pi": 3.141
}
)"_json; // parse explicitly
auto j3 = json::parse("{ \"happy\": true, \"pi\": 3.141 }"); // explicit conversion to string
std::string s = j.dump(); // {\"happy\":true,\"pi\":3.141} // serialization with pretty printing
// pass in the amount of spaces to indent
std::cout << j.dump(4) << std::endl;
// {
// "happy": true,
// "pi": 3.141
// }

read from file/save to file

// read a JSON file
std::ifstream i("file.json");
json j;
i >> j; // write prettified JSON to another file
std::ofstream o("pretty.json");
o << std::setw(4) << j << std::endl;

Arbitrary types conversions

namespace ns {
// a simple struct to model a person
struct person {
std::string name;
std::string address;
int age;
};
}

normal method

ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};

// convert to JSON: copy each value into the JSON object
json j;
j["name"] = p.name;
j["address"] = p.address;
j["age"] = p.age; // ... // convert from JSON: copy each value from the JSON object
ns::person p {
j["name"].get<std::string>(),
j["address"].get<std::string>(),
j["age"].get<int>()
};

better method

using nlohmann::json;

namespace ns {
void to_json(json& j, const person& p) {
j = json{{"name", p.name}, {"address", p.address}, {"age", p.age}};
} void from_json(const json& j, person& p) {
j.at("name").get_to(p.name);
j.at("address").get_to(p.address);
j.at("age").get_to(p.age);
}
} // namespace ns // create a person
ns::person p {"Ned Flanders", "744 Evergreen Terrace", 60}; // conversion: person -> json
json j = p; std::cout << j << std::endl;
// {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} // conversion: json -> person
auto p2 = j.get<ns::person>(); // that's it
assert(p == p2);

That's all! When calling the json constructor with your type, your custom to_json method will be automatically called. Likewise, when calling get<your_type>() or get_to(your_type&), the from_json method will be called.

How do I convert third-party types?

namespace nlohmann {

template <typename T>
struct adl_serializer {
static void to_json(json& j, const T& value) {
// calls the "to_json" method in T's namespace
} static void from_json(const json& j, T& value) {
// same thing, but with the "from_json" method
}
}; }

How can I use get() for non-default constructible/non-copyable types?

struct move_only_type {
move_only_type() = delete;
move_only_type(int ii): i(ii) {}
move_only_type(const move_only_type&) = delete;
move_only_type(move_only_type&&) = default; int i;
}; namespace nlohmann {
template <>
struct adl_serializer<move_only_type> {
// note: the return type is no longer 'void', and the method only takes
// one argument
static move_only_type from_json(const json& j) {
return {j.get<int>()};
} // Here's the catch! You must provide a to_json method! Otherwise you
// will not be able to convert move_only_type to json, since you fully
// specialized adl_serializer on that type
static void to_json(json& j, move_only_type t) {
j = t.i;
}
};
}

examples

#pragma once

#include <nlohmann/json.hpp>
using json = nlohmann::json;
#include "sensor_data.h"
#include "rfid_info.h" namespace nlohmann {
template <>
struct adl_serializer<SensorData> {
// note: the return type is no longer 'void', and the method only takes
// one argument
static SensorData from_json(const json& j) {
SensorData sensor_data;
sensor_data.sensor_identify = j.at("SensorIdentify").get<string>();
return sensor_data;
} // Here's the catch! You must provide a to_json method! Otherwise you
// will not be able to convert move_only_type to json, since you fully
// specialized adl_serializer on that type
static void to_json(json& j, SensorData t) {
j = json{ {"SensorIdentify",t.sensor_identify},{"SensorType",t.sensor_type },{"Data",t.data} };
}
};
template <>
struct adl_serializer<RfidInfo> {
// note: the return type is no longer 'void', and the method only takes
// one argument
static RfidInfo from_json(const json& j) {
RfidInfo rfid_info;
rfid_info.identify = j.at("Identify").get<string>();
return rfid_info;
} // Here's the catch! You must provide a to_json method! Otherwise you
// will not be able to convert move_only_type to json, since you fully
// specialized adl_serializer on that type
static void to_json(json& j, RfidInfo t) {
j = json{ { "Identify",t.identify },{ "Position",0 } };
}
};
}

Binary formats(BSON...)

// create a JSON value
json j = R"({"compact": true, "schema": 0})"_json; // serialize to BSON
std::vector<std::uint8_t> v_bson = json::to_bson(j); // 0x1B, 0x00, 0x00, 0x00, 0x08, 0x63, 0x6F, ... // roundtrip
json j_from_bson = json::from_bson(v_bson);

Reference

History

  • 20191012: created.

Copyright

nlohmann 最优秀的C++序列化工具库 详细入门教程的更多相关文章

  1. Python 数据处理库 pandas 入门教程

    Python 数据处理库 pandas 入门教程2018/04/17 · 工具与框架 · Pandas, Python 原文出处: 强波的技术博客 pandas是一个Python语言的软件包,在我们使 ...

  2. 程序员用于机器学习编程的Python 数据处理库 pandas 入门教程

    入门介绍 pandas适合于许多不同类型的数据,包括: · 具有异构类型列的表格数据,例如SQL表格或Excel数据 · 有序和无序(不一定是固定频率)时间序列数据. · 具有行列标签的任意矩阵数据( ...

  3. 【荐】PHP采集工具curl快速入门教程

    为什么要用CURL? CURL(Client URL Library Functions)是一个利用URL语法在命令行方式下工作的文件传输工具.它支持很多协议:FTP, FTPS, HTTP, HTT ...

  4. 信息收集工具recon-ng详细使用教程

    前言: 最近在找Recon-ng详细一点的教程,可是Google才发现资料都很零散而且不详细,所以我打算具体写一下.Recon-ng在渗透过程中主要扮演信息收集工作的角色,同时也可以当作渗透工具,不过 ...

  5. [C++]Linux之图形界面编程库[curses库]之入门教程

    1. 安装 //方法一 sudo apt-get install libncurses5-dev [ ubuntu 16.04:亲测有效] //方法二 sudo apt-get install ncu ...

  6. 自动化测试工具 Test Studio入门教程

    Test Studio安装 可以到下载试用版 官网 http://www.telerik.com/teststudio , 装完以后需要装silverlight 安装好了,主界面是介个样子的 Test ...

  7. Modbus 仿真测试工具 Mod_Rssim 详细图文教程

    Mod_RSsim是一款轻量级的Modbus从机模拟器,它可以模拟ModBusTCP和ModBusRTU的从机,能够同时模拟254个被控站,软件使用简单方便,可以满足一般的主机调试. 官方网站:www ...

  8. Google FlatBuffers——开源、跨平台的新一代序列化工具

    前段时间刚试用了一个序列化工具cereal,请看cereal:C++实现的开源序列化库,打算再总结下我对google proto buf序列化库的使用呢, 结果还没动手,大Google又出了一个新的. ...

  9. Lo-Dash – 替代 Underscore 的优秀 JS 工具库

    前端开发人员大都喜欢 Underscore,它的工具函数很实用,用法简单.这里给大家推荐另外一个功能更全面的 JavaScript 工具——Lo-Dash,帮助你更好的开发网站和 Web 应用程序. ...

随机推荐

  1. Laravel 中使用 swoole 项目实战开发案例二 (后端主动分场景给界面推送消息)

    推荐阅读:Laravel 中使用 swoole 项目实战开发案例一 (建立 swoole 和前端通信)​ 需求分析 我们假设有一个需求,我在后端点击按钮 1,首页弹出 “后端触发了按钮 1”.后端点了 ...

  2. 高仿 django插拔式 及 settings配置文件

    目录 基于django中间件实现插拔式 仿django settings 基于django中间件实现插拔式 start.py from notify import * send_all('好嗨哦') ...

  3. 如何用Postman做接口测试

    postman介绍&测试准备: postman介绍:postman是一个开源的接口测试工具,无论是做单个接口的测试还是整套测试脚本的拨测都非常方便. 前期准备:测试前,需要安装好postman ...

  4. Python基础-day01-8

    变量的基本使用 程序就是用来处理数据的,而变量就是用来存储数据的 目标 变量定义 变量的类型 变量的命名 01. 变量定义 在 Python 中,每个变量 在使用前都必须赋值,变量 赋值以后 该变量 ...

  5. NPM 问题汇总

    1. Error: setuid user id does not exist Error: setuid user id does not exist at /usr/local/lib/node_ ...

  6. 在Ubuntu 18.04系统上安装Pydio Cells详细图文教程

    前言   基于云的协作工具Pydio cell提供了一系列灵活的特性,包括应用内消息传递.文件共享和版本控制.下面逐步介绍安装过程. Pydio cell最初是一个简单的基于云的文件共享系统,但经过升 ...

  7. 关于css布局的记录(二) --网格布局

    网格布局 学习来自阮一峰老师的教程网格布局和网络上的一些资料的学习 1.定义: 顾名思义,网格布局是将页面按行(row)和列(column)划分成一个个网格来进行布局 使用方法:display:gri ...

  8. Spring Boot 2.X 国际化

    国际化文件的编写 messages.properties init project 7月前 messages_en_US.properties init project 7月前 messages_zh ...

  9. net.sf.json将string转为map

    背景 改一个以前的项目,项目里只有这个包,虽然我想用gson或者fastjson,然而并不想引入新的jar.于是使用这个,特此记录,感觉贼不好用. 实现代码 entity.getData()的值:{a ...

  10. python高阶函数——map/reduce

    python 内置了map()和reduce()函数 1.map()函数 map()函数接收两个参数,一个是函数,一个是可迭代对象Iterable,map将传入的函数依次作用于序列的每一个元素.并把结 ...