nlohmann::json万能数据结构

DinS          Written on 2018/2/27

本文介绍nlohmann::json的神奇扩展用法,请确保阅读过《nlohmann::json概述与基础用法》。

nlohmann的json绝对不是json那么简单。

一、完美支持stl

我们往json里放了一个2维数据,也就是一个表,这是非常常见的,运行结果:

完全可以正常运行!
再来点更复杂的

运行结果:

二、支持自定义结构体

更神奇的是还可以支持自定义类型,只要我们给出该类型与json的转换关系即可。

这里我们写了一个结构体Person,放到了命名空间magic里,然后在这个命名空间里定义了两个函数,json在执行转换时就调用这两个函数。
写法是固定的,照着写即可。注意from_json里要用get而不是[]。
定义好这个后我们就可以写如下代码:

运行结果:

神奇!

三、支持自定义类

更加雄心勃勃的计划是能否装载复杂的class?
先写一个类

这个类看起来比较复杂了,主要是成员变量复杂。
然后声明了两个友元,提供类与json相互转化的方法,之所以声明友元是因为转化需要直接操作成员变量。接下来是友元的实现。

大图点击这里

一点都不复杂,跟结构体是同等规模的。这是因为json库本身提供了从stl转到json的方法,可以直接调用。
这里还涉及到了自定义结构体Person的转化,因为我们提供了转化方法,所以这里也可以直接写。初始化列表确实是好用。
定义完这些,可以写如下代码。

运行结果:

大图点击这里

是成功的!
如果打印出节点,可以看到json内部是如何储存这个ComplexOne类的。本质上还是字符串,也就是说对于任何一个自定义类,当我们将其插入json时,json自动调用to_json把这个类翻译成字符串。当我们get时,json调用from_json实例化一个新的类并返回。拿到这个新的类,我们可以使用类成员函数操作,就跟正常的一样。

当然使用自定义类有几个注意事项,可以去官网查看。
还有json也不是完全万能的,比如不能放指针,这个跟json格式不符。
其他的一些用法,比如获得指针或引用,以及二进制压缩等,可以去官网查看。

这种万能型数据结构,特别适合做信使,在不同的模块间进行传递,这也是OO编程的利器。

四、json蕴含的OO思想

我们使用的数据库,都是所谓的关系型数据库,使用SQL语句来操作。更具体一点,数据库里面都是各种表,表与表进行某种链接,表内存储数据实体。这种关系型数据库与面向对象思想是不兼容的。

但是json就很有意思了,你可以把它视为一种面向对象的数据库。怎么讲?
面向对象通常会出现继承,这是一个树状图,而json的存储方式刚好是这样的。比如可以写如下代码:
json OOD
OOD[“Animal”][“Bird”][“Sparrow”] = vector<Sparrow>()
这背后蕴含的是sparrow这个数据实体是animal->bird->sparrow这个路径下自然延展的结果。
OOD[“Animal”][“Bird”][“Swallow”] = map<string, Swallow>()
如果我们的每只燕子都有名字,那么可以通过map查询。
得益于json库支持自定义类型,我们可以把class存储到json里面,并根据需要获取拷贝或引用。
这跟OO又有什么关系呢?
我们可以轻易获取OOD[“Animal”][“Bird”]这个节点,这意味着什么?这意味着Bird节点下的Sparrow和Swallow都一并获得了。换言之我们可以按照OO的思路存储数据,并且可以轻易地在继承体系中获取任意一个节点之下的数据。
不需要关系型数据库的知识和操作,我们用json存储数据自然而然就是OO了。