C++json库nlohmannjson使用介绍

这篇具有很好参考价值的文章主要介绍了C++json库nlohmannjson使用介绍。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、简介

最近项目中需要使用C++ Json序列化和反序列化,顺便调研了下目前比较好用的C++ json库,发现nlohmann/json应该是其中相对较好的json库。nlohmann/json有如下主要优点:

1、语法比较直观,类似于Python。

2、要使用nlohmann/json,只需要引入头文件json.hpp。无需引入lib之类的。

#include <nlohmann/json.hpp>

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

3、经过非常多的测试,代码质量非常高,没有内存泄漏。

4、内存效率、速度相对其它库较高。

2、实例介绍

2.1 创建Json对象

使用nlohmann/json创建Json对象,无需关心值类型,比如创建如下Json对象:

// 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}
  }}
};
2.2 序列/反序列化

在class/struct内部定义NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, …)

class Address
{
	std::string street;
	int housenumber;
	int postcode;
public:
	NLOHMANN_DEFINE_TYPE_INTRUSIVE(Address, street, housenumber, postcode)
};
字符串转成class/struct
std::string strTemp =(R"({"street": "test", "housenumber": 0, "postcode": 0})";
Address temp = nlohmann::json::parse(strTemp).get<Address>();
class/struct转成字符串
Addree temp{"Test", 0, 0};
nlohmann::json jsonTemp = temp;
std::string strTemp = jsonTemp.dump();

为了方便序列/反序列化,可以封装下面两个接口:

template<class T>
   static void deserialize(const std::string &str, T &value)
   {
       if (str.size() <= 0)
           return;
       value = parse(str).template get<T>();
   }
template<class T>
    static void serialize(const T &value, std::string &str)
    {
        str = json(value).dump();
    }

3、遇到的问题及解决办法

3.1 strings参数比class/struct的参数少,反序列化崩溃

实际项目中,json使用未必非常标准,有解析strings参数比较少的需求。比如2.2中类Address

std::string strTemp =(R"({"street": "test", "housenumber": 0})";
Address temp = nlohmann::json::parse(strTemp).get<Address>();

strTemp少了postcode,执行第二行代码就会崩溃。

解决办法

打开nlohmann/json.hpp找到源码

#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); 

将其改成

#define NLOHMANN_JSON_FROM(v1) if(nlohmann_json_j.contains(#v1)){nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);}

相比源码,就加了contains的判断,若待解析的json没有对应字段,就不作处理。

3.2 strings包含中文、“\"等反序列化崩溃

strings包含中文、“\“等“特殊字符”,用nlohmann::json反序列化就会崩溃。跟大多数json库一样,nlohmann::json是不支持中文、”\"等“特殊字符”的,因此需要先替换strings中的特殊字符,再反序列化。

3.3 类型必须匹配,数字无法转成string

实际项目中协议定的某些字段,经常出现数字、string混用的情况。nlohmann/json默认实现要求反序列化的目标class/struct参数类型和strings中完美匹配,否则解析过程中崩溃。

解决办法

原代码

template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
{
    if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
    {
         JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); 
    }
    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}

改造后

template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
{
    if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
    {
        /* 为了提高健壮性,对于json中非string的类型,也将其转成string */
        s = to_string(j);
        return;
        /* JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); */
    }
    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
3.4 NLOHMANN_DEFINE_TYPE_INTRUSIVE不支持class/struct参数过多(超过63个)

NLOHMANN_DEFINE_TYPE_INTRUSIVE并不能无限展开,nlohmann/json默认支持63个参数。

解决方案

NLOHMANN_DEFINE_TYPE_INTRUSIVE的定义如下:

#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...)  \
    friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
    friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }

NLOHMANN_DEFINE_TYPE_INTRUSIVE的原理就是用NLOHMANN_JSON_EXPAND,1个NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, …))可以支持63个,超过可以另起1个,如下:文章来源地址https://www.toymoban.com/news/detail-638504.html

struct StructTest
{
	std::string param1;
	std::string param2;
	...
	std::string param63;
	std::string param64;
	...

    friend void from_json(const nlohmann::json& nlohmann_json_j, StructTest& nlohmann_json_t)
    {
        NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(func, param1, param2, ..., param63));
		NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(func, param64, param65, ...));
    }
    friend void to_json(nlohmann::json& nlohmann_json_j, const StructTest& nlohmann_json_t)
    {
        NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(func, param1, param2, ..., param63));
		NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(func, param64, param65, ...));
    }
};

到了这里,关于C++json库nlohmannjson使用介绍的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • c语言-json开源库cJSON的使用

    一、cJSON的介绍     cJSON是一个开源的JSON解析器,用于解析JSON数据。它是由纯C语言实现,因此跨平台性好,移植简单。 下载地址: 二、移植方法     cJSON只有一个cjson.c和cjson.h文件,可以很方便地集成到其他项目中。cJSON支持将JSON数据解析为cJSON对象,也支持将cJSON对象转

    2024年04月29日
    浏览(22)
  • 主流开发语言和开发环境介绍

    Tips:TIOBE排行榜是根据互联网上有经验的程序员、课程和第三方厂商的数量,并使用搜索引擎(如Google、Bing、Yahoo!)以及Wikipedia、Amazon、YouTube和Baidu(百度)统计出排名数据,只是反映某个编程语言的热门程度,并不能说明一门编程语言好不好,或者一门语言所编写的代码数

    2024年02月21日
    浏览(28)
  • 主流开发语言与环境介绍

    随着计算机科学的不断发展,各种编程语言和开发环境层出不穷。选择一种适合自己的主流开发语言和环境是每个开发者都必须面临的问题。本文将为大家介绍几种目前最为流行的主流开发语言和环境,帮助读者选择合适的工具进行开发。 Python是一种高级、通用、解释型的编

    2024年03月13日
    浏览(30)
  • 介绍几种Go语言开发的IDE

    1.前言 Go语言作为一种新兴的编程语言,近年来受到了越来越多的关注。 它以其简洁、高效和并发性能而闻名,被广泛应用于各种软件开发项目中。 为了提高开发效率和代码质量,选择一款合适的集成开发环境(IDE)是非常重要的。 本文将介绍几种常用的Go语言IDE,并对它们

    2024年02月05日
    浏览(33)
  • go 语言中 json.Unmarshal([]byte(jsonbuff), &j) 字节切片得使用场景

    struct_tag的使用 在上面的例子看到,我们根据结构体生成的json的key都是大写的,因为结构体名字在go语言中不大写的话,又没有访问权限,这种问题会影响到我们对json的key的名字,所以go官方给出了struct_tag的方法去修改生成json时,对应key的名字 map 生成json json解析到map json解

    2024年01月23日
    浏览(29)
  • 基于C#语言的GUI开发,主要介绍WPF框架

    下面是几种常见基于.Net的界面开发框架,都是Microsoft提供,下面简介由GPT生成 WinForms (Windows Forms WPF (Windows Presentation Foundation) UWP (Universal Windows Platform) MAUI (Multi-platform App UI) WinForms(Windows Forms): 介绍: WinForms是由Microsoft提供的用于开发Windows桌面应用程序的UI框架。它使用简单

    2024年02月03日
    浏览(32)
  • <HarmonyOS第一课>ArkTS开发语言介绍——闯关习题及答案

    判断题 1.循环渲染ForEach可以从数据源中迭代获取数据,并为每个数组项创建相应的组件。( 对 ) 2.@Link变量不能在组件内部进行初始化。( 对 ) 单选题 1.用哪一种装饰器修饰的struct表示该结构体具有组件化能力?( A ) A. @Component B. @Entry C. @Builder D. @Preview 2.用哪一种装饰

    2024年02月07日
    浏览(33)
  • 软件开发中常用数据结构介绍:C语言队列

    工作之余来写写C语言相关知识,以免忘记。今天就来聊聊 C语言实现循环队列 ,我是分享人M哥,目前从事车载控制器的软件开发及测试工作。 学习过程中如有任何疑问,可底下评论! 如果觉得文章内容在工作学习中有帮助到你,麻烦 点赞收藏评论+关注 走一波!感谢各位的

    2024年02月11日
    浏览(36)
  • 零基础快速上手HarmonyOS ArkTS开发1---运行Hello World、ArkTS开发语言介绍

    在华为开发者大会2023年8月4日(HDC.Together)大会上,HarmonyOS 4正式发布,其实在2021年那会学习了一点鸿蒙的开发: 不过因为现在的鸿蒙手机完全兼容Android应用,所以学习动力也不是很足,一直就搁置了,直到今年华为官方出了这么一则消息才让我对于学习它有一种紧迫感了,如

    2024年02月05日
    浏览(40)
  • 入门Python编程:了解计算机语言、Python介绍和开发环境搭建

    计算机语言是用来控制计算机行为的一种语言,通过它可以告诉计算机该做什么。计算机语言和人类语言在本质上没有太大区别,只是交流的对象不同。 计算机语言发展经历了三个阶段: 1. 机器语言 机器语言使用二进制编码来编写程序。 执行效率高,但编写起来麻烦。 2

    2024年02月09日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包