本文首发于个人博客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. Java环境变量配置超详细教程

    https://blog.csdn.net/Mxdon_on/article/details/89461365 概述 Java的环境配置并不是特别难,但是对刚上手的新手来说确实是一个大问题 首先下载j ...

  2. uni-app自定义app端的扫码界面

    记得当时是在西班牙有这样的一个需求,需要自定义扫码页面,还需要加上西班牙文,当时是在一个组件里面找到了这样的一个方法,全文大部分使用的app端的Native里面的方法,记录一下,跑路了项目代码要删库了 ...

  3. ssh服务介绍及配置

    一.ssh介绍 1.什么是 ssh ssh 是 Secure Shell 的缩写,是一个建立在应用层上的安全远程管理协议.ssh 是目前较为可靠的传输协议,专为远程登录会话和其他网络服务提供安全性.利 ...

  4. GrimTheRipper: 1 Vulnhub Walkthrough

    靶机下载: https://www.vulnhub.com/entry/grimtheripper-1,350/ 主机层面端口扫描: ╰─ nmap -p1-65535 -A 10.10.202.15 ...

  5. vue路由进阶

    一..全局路由前置守卫 1.首先看一下文档结构 Dashboard和Login是一级页面  home about mine是在Dashboard下的二级页面 2.router.js代码如下 impor ...

  6. 流程图软件 drawio 免费 github开源

    做程序需要画流程图,发现迅捷流程图的在线版挺好用的,但是,它的导出只允许VIP会员,不是VIP会员只能导出xsd文件,而且要注册账号,极为麻烦. 在知乎看到了一位网友的评论,有一款软件和迅捷流程图一模 ...

  7. MySql 更新死锁问题 Deadlock found when trying to get lock; try restarting transaction

    文章导航-readme MySql 更新死锁问题 Deadlock found when trying to get lock; try restarting transaction 1.场景 //t ...

  8. 精通awk系列(15):awk数据类型和字面量

    回到: Linux系列文章 Shell系列文章 Awk系列文章 数据类型 gawk有两种基本的数据类型:数值和字符串.在gawk 4.2.0版本中,还支持第三种基本的数据类型:正则表达式类型. 数据是 ...

  9. Socket实现简易聊天室,Client,Server

    package seday08; import java.io.BufferedWriter;import java.io.OutputStream;import java.io.OutputStre ...

  10. 番茄助手 最新 Visual Assist X 适应于VS2019 VS2017 VS2015 VS2013 亲测可用

    番茄助手 最新 Visual Assist X 适应于VS2019 VS2017 VS2015 VS2013 亲测可用 如图: 颜色已经改变: 下载说明: /* INSTALLATION 0) Uni ...