c++11:nlohmann::json进阶使用ordered_json

Posted 10km

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++11:nlohmann::json进阶使用ordered_json相关的知识,希望对你有一定的参考价值。

nlohmann::json是非常好用的一个json开源解析库.nlohmann/json的源码是基于C++11标准写的,整个源码就是一个文件 nlohmann/json.hpp,引用非常方便。
关于nlohmann/json的基本使用官网(https://github.com/nlohmann/json)上有比较详细的介绍。这里不再赘述,本文主要是介绍在nlohmann/json的基本使用之外一些我在使用 nlohmann/json 用到的一些扩展功能和重要但不太被了解的特性。

ordered_json

先看一个简单的nlohmann/json调用的例子:
nlohmann_json_test1.cpp

#include <iostream>
#include "nlohmann/json.hpp"
using namespace nlohmann;
int main()

    json j;
    j["tom"] = "hello";
    j["jerry"] = "world";
    std::cout << "j : " << j.dump(4) << std::endl;

输出结果是:

j : 
    "jerry": "world",
    "tom": "hello"

虽然我们先将"tom=hello"加入json对象,但实际输出的JSON时对字段名进行了排序,"tom": "hello"这一条反而输出到"jerry": "world"之后了。

这是为什么呢?我们先说说 nlohmann/json 的基本概况
阅读nlohmann/json的源码,就可以知道整个nlohmann/json项目都是基于C++11模板类技术设计的,其中用到了很多C++11提供的模板技术,可以说是C++模板编程的经典应用案例,我从中也学到不少模板编程的技巧。
而且nlohmann::jsonnlohmann/json中主要使用的类,它其实是模板类nlohmann::basic_json的特例化实现,nlohmann::basic_json中所有json字段其实是保存在K-V映射形式(Map)对象中的,而nlohmann::basic_json默认使用std::map作为保存K-V映射的数据对象
参见:

template<template<typename U, typename V, typename... Args> class ObjectType =
         std::map,
         template<typename U, typename... Args> class ArrayType = std::vector,
         class StringType = std::string, class BooleanType = bool,
         class NumberIntegerType = std::int64_t,
         class NumberUnsignedType = std::uint64_t,
         class NumberFloatType = double,
         template<typename U> class AllocatorType = std::allocator,
         template<typename T, typename SFINAE = void> class JSONSerializer =
         adl_serializer,
         class BinaryType = std::vector<std::uint8_t>>
class basic_json;

std::map是STL提供的模板类,它对K是排序的。所以就出现上面的例子的结果。

如果你的应用中并不在意这个顺序问题,那就可以不用看这篇文章了。
而我在使用nlohmann/json的场景却是很关注这个顺序的,我希望输出的JSON的字段顺序与我加入字段的顺序一致。我并不希望nlohmann/json给我排序。

这可怎么办?

我又去看了nlohmann/json的官网,发现距离我使用的版本3.7.3,已经有多次升级,现在的新版本已经是3.10.4了,nlohmann/json从3.9.0开始增加了一个nlohmann::basic_json的特例化实现类ordered_json,这个类就可以实现保留插入key的顺序。
如下是json.hpp中对ordered_json的说明

/*!
@brief ordered JSON class

This type preserves the insertion order of object keys.

@since version 3.9.0
*/
using ordered_json = basic_json<nlohmann::ordered_map>;

  // namespace nlohmann

真是及时雨啊,果断更新版本,
再将前面代码中j变量的类型改为ordered_json就OK.
nlohmann_json_test2.cpp

#include <iostream>
#include "nlohmann/json.hpp"
using namespace nlohmann;
int main()

    ordered_json j;
    j["tom"] = "hello";
    j["jerry"] = "world";
    std::cout << "j : " << j.dump(4) << std::endl;

输出顺序就改变了,就是key添加的顺序:

j : 
    "tom": "hello",
    "jerry": "world"

以上是关于c++11:nlohmann::json进阶使用ordered_json的主要内容,如果未能解决你的问题,请参考以下文章

c++11:nlohmann::json进阶使用应用adl_serializer解决第三方数据类型(such as uri)的序列化和反序列化

C++ I/O 进阶

C#语言进阶——2.C# 的 I/O 操作

printf的用法进阶

Redis介绍使用及进阶

进阶之路(基础篇) - 004 I/O的模拟量输出