本文首发于个人博客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. 安装Django、Nginx和uWSGI

    安装Django.Nginx和uWSGI 1.确定已经安装了2.7版本的Python: 2.安装python-devel yum install python-devel 3.安装uwsgi pip ...

  2. 201871010119-帖佼佼《面向对象程序设计(java)》第十二周学习总结

    博客正文开头格式: 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nw ...

  3. NodeJS4-5静态资源服务器实战_优化压缩文件

    浏览器控制台看一下RequestHeader有一个Accept-Encoding,而RespondHeaders中也会有一个Content-Encoding和他进行对应. Accept-Encodin ...

  4. git 知识,适合新手 滤清思路

    1,密钥 (公钥和私钥) @ 公钥放在服务器上(说白了这里的服务器就是远程仓库, 就是谁建立的远程仓库这个公钥就放在他的ssh设置那) @ 私钥 放在本地就行,不用动,就是你生产密钥的.ssh 文件里 ...

  5. docker 创建.netcore2.2 api容器 以及连接mysql容器

    1]环境说明 操作系统:Window 10 专业版 开发工具 Vs2019专业版 Docker:  Docker for Windows  docker在windows上安装完毕之后可以看到 2]拉取 ...

  6. Linux下监控用户操作轨迹

    在实际工作当中,都会碰到误删除.误修改配置文件等事件.如果没有堡垒机,要在linux系统上查看到底谁对配置文件做了误操作,特别是遇到删库跑路的事件,当然可以通过history来查看历史命令记录,但如果 ...

  7. Docker从入门到掉坑(四):上手k8s避坑指南

    在之前的几篇文章中,主要还是讲解了关于简单的docker容器该如何进行管理和操作,在接下来的这篇文章开始,我们将开始进入对于k8s模块的学习 不熟悉的可以先回顾之前的章节,Docker教程系列文章将归 ...

  8. Python爬虫实战:批量下载网站图片

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: GitPython PS:如有需要Python学习资料的小伙伴可以 ...

  9. threejs 绘制辅助网格

    GridHelper.js可以帮助绘制一个xz平面网格,它没有提供更多的参数,所以不能用于生成xy网格. xy网格实现代码如下: var size = 6000; var divisions = 50 ...

  10. IT兄弟连 HTML5教程 CSS3属性特效 渐变1

    渐变背景一直以来在Web页面中都是一种常见的视觉元素.但一直以来,Web设计师都是通过图形软件设计这些渐变效果,然后以图片形式或者背景图片的形式运用到页面中.Web页面上实现的效果,仅从页面的视觉效果 ...