Json文件解析(上)
Json文件解析(上)
代码地址:https://github.com/nlohmann/json
- 设计目标
- 赞助商
- 积分
- 例子
- JSON作为一流的数据类型
- 序列化/反序列化
- 类似STL的访问
- 从STL容器转换
- JSON指针和JSON补丁
- JSON合并补丁
- 隐式转换
- 到/从任意类型的转换
- 专门进行枚举转换
- 二进制格式(BSON,CBOR,MessagePack和UBJSON)
- 支持的编译器
- 执照
- 联系
- 谢谢
- 二手第三方工具
- 使用JSON for Modern C ++的项目
- 笔记
- 执行单元测试
设计目标
那里有无数的JSON库,每个库甚至都有其存在的理由。班有以下设计目标:
- 直观的语法。在Python等语言中,JSON感觉就像是一流的数据类型。使用了现代C ++的所有操作符魔术,以在代码中实现相同的感觉。查看以下示例,将了解意思。
- 微不足道的整合。整个代码包含一个头文件json.hpp。没有库,没有子项目,没有依赖项,没有复杂的构建系统。该类用香草C ++ 11编写。总而言之,一切都不需要调整编译器标志或项目设置。
- 认真测试。项目经过严格的单元测试,涵盖了100%的代码,包括所有异常行为。此外,使用Valgrind和Clang网络检查是否有内存泄漏。Google OSS-Fuzz还针对所有解析器24/7运行模糊测试,到目前为止,有效执行了数十亿次测试。为了保持高质量,该项目遵循核心基础设施计划(CII)最佳实践。
其方面对而言并不那么重要:
- 存储效率。每个JSON对象的开销为一个指针(联合的最大大小)和一个枚举元素(1个字节)。默认归纳使用以下C ++数据类型:std::string用于字符串int64_t,uint64_t或double数字,std::map对象,std::vector数组和bool布尔值。但是,可以根据basic_json需要对通用类进行模板化。
- 速度。当然,那里有更快的JSON库。但是,如果目标是通过使用单个标头添加JSON支持来加快开发速度,那么该库就是理想之选。如果知道如何使用std::vector或std::map,那么已经设置好了。
积分
json.hpp是此处single_include/nlohmann或发布的单个必需文件。需要添加
#包括 < nlohmann / json.hpp >
//为了方便
使用 json = nlohmann :: json;
到要处理JSON的文件,并设置必要的开关以启用C ++ 11(例如,-std=c++11对于GCC和Clang)。
可以进一步使用file include/nlohmann/json_fwd.hpp进行前向声明。json_fwd.hpp的安装(作为cmake安装步骤的一部分)可以通过设置来实现-DJSON_MultipleHeaders=ON。
CMake的
也可以nlohmann_json::nlohmann_json在CMake中使用接口目标。此目标填充适当的使用要求,INTERFACE_INCLUDE_DIRECTORIES以指向适当的包含目录和INTERFACE_COMPILE_FEATURES必要的C ++ 11标志。
外部
要从CMake项目中使用此库,可以直接从中找到,find_package()并使用生成的程序包配置中的命名空间导入目标:
#CMakeLists.txt
find_package(nlohmann_json 3.2.0 REQUIRED)
...
add_library(foo ...)
...
target_link_libraries(foo PRIVATE nlohmann_json :: nlohmann_json)
软件包配置文件nlohmann_jsonConfig.cmake可以在安装树中使用,也可以在构建树之外直接使用。
嵌入式的
要将库直接嵌入到现有CMake项目中,请将整个源代码树放置在子目录中,然后调用add_subdirectory()CMakeLists.txt文件:
#通常不那么关心第三方库的测试是
#从自己的项目的代码运行。
设置(JSON_BuildTests OFF CACHE INTERNAL “”)
#如果仅在私有源文件中包含此第三方,则
#在安装主项目时不需要安装。
#集(JSON_Install OFF CACHE INTERNAL “”)
#请勿使用include(nlohmann_json / CMakeLists.txt),因为会附带
#会导致构建中断的意外后果。通常
#鼓励(虽然不一定有据可查这样)使用
#包括(...),用于其项目的CMake反正拉动。
add_sub目录(nlohmann_json)
...
add_library(foo ...)
...
target_link_libraries(foo PRIVATE nlohmann_json :: nlohmann_json)
嵌入式(FetchContent)
从CMake v3.11开始, FetchContent可以作为配置类型的依赖项自动下载资源库。
例:
包括(FetchContent)
FetchContent_Declare(json
GIT_REPOSITORY https://github.com/nlohmann/json.git
GIT_TAG v3.7.3)
FetchContent_GetProperties(json)
如果(NOT json_POPULATED)
FetchContent_Populate(json)
add_subdirectory($ {json_SOURCE_DIR} $ {json_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
target_link_libraries(foo PRIVATE nlohmann_json :: nlohmann_json)
注意:仓库https://github.com/nlohmann/json的下载量很大。包含用于基准测试的所有数据集。可能需要依赖较小的存储库。例如,可能想用https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent替换上面的URL
同时支持
为了允许项目支持外部提供的或嵌入式JSON库,可以使用类似于以下内容的模式:
# Top level CMakeLists.txt
project(FOO)
...
option(FOO_USE_EXTERNAL_JSON "Use an external JSON library" OFF)
...
add_subdirectory(thirdparty)
...
add_library(foo ...)
...
# Note that the namespaced target will always be available regardless of the
# import method
target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
# thirdparty/CMakeLists.txt
...
if(FOO_USE_EXTERNAL_JSON)
find_package(nlohmann_json 3.2.0 REQUIRED)
else()
set(JSON_BuildTests OFF CACHE INTERNAL "")
add_subdirectory(nlohmann_json)
endif()
...
thirdparty/nlohmann_json 然后是此源树的完整副本。
包管理Package Managers
If you are using OS X and Homebrew, just type brew tap nlohmann/json
and brew install nlohmann-json
and you're set. If you want the bleeding edge rather than the latest release, use brew install nlohmann-json --HEAD
.
If you are using the Meson Build System, add this source tree as a meson subproject. You may also use the include.zip
published in this project's Releases to reduce the size of the vendored source tree. Alternatively, you can get a wrap file by downloading it from Meson WrapDB, or simply use meson wrap install nlohmann_json
. Please see the meson project for any issues regarding the packaging.
The provided meson.build can also be used as an alternative to cmake for installing nlohmann_json
system-wide in which case a pkg-config file is installed. To use it, simply have your build system require the nlohmann_json
pkg-config dependency. In Meson, it is preferred to use the dependency()
object with a subproject fallback, rather than using the subproject directly.
If you are using Conan to manage your dependencies, merely add nlohmann_json/x.y.z
to your conanfile
's requires, where x.y.z
is the release version you want to use. Please file issues here if you experience problems with the packages.
If you are using Spack to manage your dependencies, you can use the nlohmann-json
package. Please see the spack project for any issues regarding the packaging.
If you are using hunter on your project for external dependencies, then you can use the nlohmann_json package. Please see the hunter project for any issues regarding the packaging.
If you are using Buckaroo, you can install this library's module with buckaroo add github.com/buckaroo-pm/nlohmann-json
. Please file issues here. There is a demo repo here.
If you are using vcpkg on your project for external dependencies, then you can use the nlohmann-json package. Please see the vcpkg project for any issues regarding the packaging.
If you are using cget, you can install the latest development version with cget install nlohmann/json
. A specific version can be installed with cget install nlohmann/json@v3.1.0
. Also, the multiple header version can be installed by adding the -DJSON_MultipleHeaders=ON
flag (i.e., cget install nlohmann/json -DJSON_MultipleHeaders=ON
).
If you are using CocoaPods, you can use the library by adding pod "nlohmann_json", '~>3.1.2'
to your podfile (see an example). Please file issues here.
If you are using NuGet, you can use the package nlohmann.json. Please check this extensive description on how to use the package. Please files issues here.
If you are using conda, you can use the package nlohmann_json from conda-forge executing conda install -c conda-forge nlohmann_json
. Please file issues here.
If you are using MSYS2, your can use the mingw-w64-nlohmann-json package, just type pacman -S mingw-w64-i686-nlohmann-json
or pacman -S mingw-w64-x86_64-nlohmann-json
for installation. Please file issues here if you experience problems with the packages.
If you are using build2
, you can use the nlohmann-json
package from the public repository https://cppget.org or directly from the package's sources repository. In your project's manifest
file, just add depends: nlohmann-json
(probably with some version constraints). If you are not familiar with using dependencies in build2
, please read this introduction. Please file issues here if you experience problems with the packages.
If you are using wsjcpp
, you can use the command wsjcpp install "https://github.com/nlohmann/json:develop"
to get the latest version. Note you can change the branch ":develop" to an existing tag or another branch。
包配置
如果使用的是裸Makefile,则可以使用pkg-config生成指向库安装位置的include标志:
pkg-config nlohmann_json --cflags
Meson构建系统的用户还可以使用系统范围的库,该库可以通过pkg-config以下方式找到:
json = dependency('nlohmann_json', required: true)
例子
除了下面的示例,可能想查看文档,其中每个函数都包含一个单独的代码示例(例如,检出emplace())。所有示例文件都可以单独编译和执行(例如,文件emplace.cpp)。
JSON作为一流的数据类型
以下是一些示例,可让了解如何使用该类。
假设要创建JSON对象
{
"pi": 3.141,
"happy": true,
"name": "Niels",
"nothing": null,
"answer": {
"everything": 42
},
"list": [1, 0, 2],
"object": {
"currency": "USD",
"value": 42.99
}
}
使用该库,可以编写:
//创建一个空结构(空)
json j;
//添加一个存储为double的数字(注意j到对象的隐式转换)
j [ “ pi ” ] = 3.141 ;
//添加一个存储为bool
j [ “ happy ” ] = true的布尔值;
//添加一个存储为std :: string
j [ “ name ” ] = “ Niels ”的字符串;
//通过传递nullptr
j [ “ nothing ” ] = nullptr来添加另一个null对象;
//在对象
j [ “ answer ” ] [ “ everything ” ] = 42 内添加一个对象;
//添加存储为标准::向量(使用初始化列表)的阵列
f] [ “列表” ] = { 1, 0, 2 };
//添加另一个对象(使用成对的初始化列表)
j [ “ object ” ] = {{ “ currency ”, “ USD ” },{ “ value ”, 42.99 }};
//相反,也可以编写(看起来与上面的JSON非常相似)
json j2 = {
{ “ pi ”,3.141 },
{ “ happy ”,true },
{ “ name ”,“ Niels ” },
{ “没有”,nullptr },
{ “答案”,{
{ “一切”,42 }
}},
{ “列表”,{ 1,0,2 }},
{ “对象”,{
{ “货币”,“美元” },
{ “值”,42.99 }
}}
};
请注意,在所有这些情况下,都无需“告诉”编译器要使用的JSON值类型。如果想明确表达或表达一些极端情况,这些函数json::array()和json::object()将有助于:
//表达空数组[]的方法
json empty_array_explicit = json :: array();
//表示空对象的方法{}
json empty_object_implicit = json({});
json empty_object_explicit = json :: object();
//一种方式来表达的键/值对的_array_ [[ “货币”, “USD”],[ “值”,42.99]]
JSON array_not_object = JSON ::阵列({{ “货币”, “ USD ” } ,{ “ value ”, 42.99 }});
序列化/反序列化
到/从字符串
可以通过附加_json到字符串文字来创建JSON值(反序列化):
//从字符串文字
json创建对象 j = “ { \” happy \“:true,\” pi \“: 3.141 } ” _json;
//甚至使用原始字符串文字
自动 j2 = R“(
{
” happy“:true,
” pi“:
3.141 }
)” _json;
请注意,不附加_json后缀,传递的字符串文字不被解析,而仅用作JSON字符串值。也就是说,json j = "{ \"happy\": true, \"pi\": 3.141 }"将只存储字符串"{ "happy": true, "pi": 3.141 }"而不是解析实际对象。
上面的示例也可以使用来明确表示json::parse():
//明确解析
自动 j3 = json :: parse( “ { \” happy \“:true,\” pi \“:3.141} ”);
还可以获取JSON值的字符串表示形式(序列化):
//明确转换为字符串
std :: string s = j.dump(); // {“ happy”:true,“ pi”:3.141}
//通过漂亮的打印进行序列化
//传递空格以缩进
std :: cout << j.dump( 4)<< std :: endl;
// {
// “ happy”:true,
// “ pi”:3.141
// }
注意序列化和赋值之间的区别:
//在JSON值中存储一个字符串
json j_string = “这是一个字符串” ;
//检索字符串值
auto cpp_string = j_string.get <std :: string>();
//检索字符串值(变量已经存在时的替代方法)
std :: string cpp_string2;
j_string.get_to(cpp_string2);
//检索序列化的值(显式JSON序列化)
std :: string serialized_string = j_string.dump();
//输出原始字符串
std :: cout << cpp_string << “ == ” << cpp_string2 << “ == ” << j_string.get <std :: string>()<< ' \ n ' ;
//输出序列化值
std :: cout << j_string << “ == ” << serialized_string << std :: endl;
.dump()始终返回序列化的值,并.get<std::string>()返回原始存储的字符串值。
请注意,该库仅支持UTF-8。当在库中存储具有不同编码的字符串时,dump()除非json::error_handler_t::replace或json::error_handler_t::ignore用作错误处理程序,否则调用可能会引发异常。
往返流(例如文件,字符串流)
还可以使用流来序列化和反序列化:
//从标准输入反序列化
json j;
std :: cin >> j;
//序列化为标准输出
std :: cout << j;
// setw操纵器过载以设置漂亮打印的缩进
std :: cout << std :: setw( 4)<< j << std :: endl;
这些运算符可用于std::istream或的任何子类std::ostream。这是文件的相同示例:
//读取JSON文件
std :: ifstream i( “ file.json ”);
json j;
>> j;
//将经过修饰的JSON写入另一个文件
std :: ofstream o( “ pretty.json ”);
o << std :: setw(4)<< j << std :: endl;
请注意,为此设置异常位failbit是不合适的。由于使用了noexcept指定符,将导致程序终止。
从迭代器范围读取
也可以从迭代器范围解析JSON;也就是从迭代器可访问的,value_type整数类型为1、2或4个字节的任何容器中,这些容器将分别解释为UTF-8,UTF-16和UTF-32。例如std::vector<std::uint8_t>,或std::list<std::uint16_t>:
std :: vector <std :: uint8_t > v = { ' t ',' r ',' u ',' e ' };
json j = json :: parse(v.begin(),v.end());
可以将迭代器保留在[begin,end)范围内:
std :: vector <std :: uint8_t > v = { ' t ',' r ',' u ',' e ' };
json j = json :: parse(v);
自定义数据源
由于parse函数接受任意迭代器范围,因此可以通过实现此LegacyInputIterator概念来提供自己的数据源。
struct MyContainer {
void advance();
const char&get_current();
};
struct MyIterator {
使用 difference_type = std :: ptrdiff_t ;
使用 value_type = char ;
使用指针= const char *;
使用 reference = const char&;
使用 iterator_category = std :: input_iterator_tag;
MyIterator&运算符 ++(){
MyContainer。前进();
返回 * 这个 ;
}
布尔 运算符!=(const MyIterator&rhs)const {
return rhs。目标!=目标;
}
引用运算符 *()const {
返回目标。get_current();
}
MyContainer * target = nullptr ;
};
MyIterator 开始(MyContainer&tgt){
return MyIterator {&tgt};
}
MyIterator 结束(const MyContainer&){
return {};
}
无效 foo(){
MyContainer c;
json j = json :: parse(c);
}
SAX接口
该库使用具有以下功能的类SAX接口:
//当解析为
null 时调用bool null();
//在解析布尔值时调用;值传递给
布尔布尔 值(布尔值);
//在解析有符号或无符号整数时调用;值传递给
bool number_integer( number_integer_t val);
bool number_unsigned( number_unsigned_t val);
//在解析浮点数时调用;值和原始字符串传递给
bool number_float( number_float_t val, const string_t&s);
//解析字符串时调用;值被传递并且可以安全地移开
布尔 字符串( string_t&val);
//分别在对象或数组开始或结束时调用。传递的元素数量(如果不知道,则传递-1)
bool start_object(std :: size_t元素);
bool end_object();
bool start_array(std :: size_t元素);
bool end_array();
//在解析对象键时调用;值被传递并且可以安全地移开
bool 键( string_t&val);
//发生解析错误时调用;字节位置,最后一个标记和一个异常被传递给
bool parse_error(std :: size_t position, const std :: string&last_token, const detail :: exception&ex);
每个函数的返回值确定是否应该进行解析。
要实现自己的SAX处理程序,请按照下列步骤操作:
- 在一个类中实现SAX接口。可以将类nlohmann::json_sax<json>用作基类,但也可以使用实现了上述功能并且将其公开的任何类。
- 创建SAX接口类的对象,例如my_sax。
- 致电bool json::sax_parse(input, &my_sax); 其中第一个参数可以是任何输入(例如字符串或输入流),第二个参数是指向SAX接口的指针。
注意,该sax_parse函数仅返回一个bool指示上一次执行的SAX事件的结果的结果。不返回 json值-由决定如何处理SAX事件。此外,在解析错误的情况下不会抛出异常-由决定如何将异常对象传递给parse_error实现。在内部,SAX接口用于DOM解析器(类json_sax_dom_parser)以及接受器(json_sax_acceptor),请参见file json_sax.hpp。
类似STL的访问
设计了JSON类,使其表现得像STL容器一样。实际上,满足了ReversibleContainer的要求。
//使用push_back创建一个数组
json j;
j.push_back(“ foo ”);
j.push_back(1);
j.push_back(true);
//还使用emplace_back
j.emplace_back( 1.78);
//
为(json :: iterator it = j.begin(); it!= j.end(); ++ it)迭代数组 {
std :: cout << * it << ' \ n ' ;
}
//基于范围的
for( auto&element:j){
std :: cout <<元素<< ' \ n ' ;
}
// getter / setter
const auto tmp = j [ 0 ] .get <std :: string>();
j [ 1 ] = 42 ;
bool foo = j.at(2);
//比较
j == “ [ \” foo \“,42,true] ” _json; //正确
//其东西
j.size(); // 3个条目
j.empty(); // false
j.type(); // json :: value_t :: array
j.clear(); //数组再次为空
//便利类型检查器
j.is_null();
j.is_boolean();
j.is_number();
j.is_object();
j.is_array();
j.is_string();
//创建一个对象
json o;
o [ “ foo ” ] = 23 ;
o [ “ bar ” ] = false ;
o [ “ baz ” ] = 3.141 ;
//还可以使用
emplace o.emplace( “ weather ”, “ sunny ”);
// //对象专用的迭代器成员函数,
用于(json :: iterator it = o.begin(); it!= o.end(); ++ it){
std :: cout <<。key()<< “:” <<。value()<< “ \ n ” ;
}
//与
for( auto&el:o.items()){
std :: cout << el。key()<< “:” << << value()<< “ \ n ” ;
}
//即使结构化绑定(C ++ 17)更容易
为(自动&[键,值]:o.items()){
std :: cout <<键<< “:” <<值<< “ \ n ” ;
}
//找到一个条目
,如果(o.contains( “富”)){
//存在与键“foo”的条目
}
//或者通过find和一个迭代器
if(o.find( “ foo ”)!= o.end()){
//有一个键为“ foo”的条目
}
//或更简单地使用count()
int foo_present = o.count( “ foo ”); // 1
int fob_present = o.count( “ fob ”); // 0
//删除条目
o.erase( “ foo ”);
Json文件解析(上)的更多相关文章
- Json文件解析(下)
Json文件解析(下) 代码地址:https://github.com/nlohmann/json 从STL容器转换 任何序列容器(std::array,std::vector,std::dequ ...
- Golang Json文件解析为结构体工具-json2go
代码地址如下:http://www.demodashi.com/demo/14946.html 概述 json2go是一个基于Golang开发的轻量json文件解析.转换命令行工具,目前支持转换输出到 ...
- PHP JSON文件解析并获取key、value,判断key是否存在
/****************************************************************************** * PHP JSON文件解析并获取key ...
- 【微信】微信小程序 微信开发工具中新创建的json文件,编译报错VM1781:2 pages/module/module.json 文件解析错误 SyntaxError: Unexpected end of JSON input
如果新创建报错:编译报错VM1781:2 pages/module/module.json 文件解析错误 SyntaxError: Unexpected end of JSON input 解决方法 ...
- Twaver的mono-desiner导出的json文件解析
以画的交换机为例,其他大概都差不多. 利用Twaver做出交换机模型如图1所示,其中,每一个端口都是一个单独的对象.具体Twaver操作流程参见网址:http://twaver.servasoft.c ...
- json 文件解析与应用
第一步:首先弄一个 json 文件 我这里成为 config.json 内容如下 { ": { , "desc":"中华人民共和国" }, &qu ...
- NPOI+Json文件解析Excel
记点笔记,加深印象!最近有个导入Excel工能需要完成,Excel列名是中文的,导入Excel我用的NPOI插件,如果不对Excel做解析,列名有可能会给我带来一些字符方面的麻烦,于是想到了一个比较l ...
- HBuilder开发移动App——manifest.json文件解析
以前做过Android App开发,对于各项配置都是在AndroidManifest.xml文件中完成的,包括权限的设定.图标.标签.App的名字.Activity注册等等 使用HBuilder开发移 ...
- json文件解析
场景 读取json文件,读取子域名扫描结果 实现 >>> import json >>> with open("C:\\Users\\Windows32\ ...
随机推荐
- windows-API劫持(API-HOOK)
API Hook ApiHook又叫做API劫持,也就是如果A程序调用了B.cll里面的C函数,我们可以做到当A调用C函数执行的时候,直接执行我们自己事先准备好的函数,之后我们在执行真正的C,当然我们 ...
- VS中光标变成方块状,输入时会把光标覆盖的部分替换掉的解决方法
按下键盘上的Insert键,切换为插入模式.
- Spring Cloud Alibaba(10)---Sentinel控制台搭建+整合SpringCloudAlibaba
上一篇博客讲了Sentinel一些概念性的东西 Spring Cloud Alibaba(9)---Sentinel概述 这篇博客主要讲 Sentinel控制台搭建,和 整合SpringCloudAl ...
- SQLFlow使用中的注意事项--设置篇
SQLFlow 是用于追溯数据血缘关系的工具,它自诞生以来以帮助成千上万的工程师即用户解决了困扰许久的数据血缘梳理工作. 数据库中视图(View)的数据来自表(Table)或其他视图,视图中字段(Co ...
- 逆向工程初步160个crackme-------1
放假在家学习的效率真的很低,看完看雪加密解密的前两章就迫不及待的找了几个crackme练习一下,顺便熟悉ollydbg的使用. 工具:exeinfope(查壳工具),ollydbg(2.10版) 1. ...
- 2020.12.20vj补题
A - Insomnia cure 题意:一共s只龙,每隔k,l,m,n只龙就会受伤,问这s只龙有多少龙是受伤的 思路:看起来题目范围并不是很多,直接进行循环判断 代码: 1 #include< ...
- java面试一日一题:java中一个对象实例的结构是什么样子的
问题:请讲下在java程序运行时一个对象实例的数据结构是什么样子的 分析:该问题主要考察对java中对象的理解,在程序运行过程中一个对象实例是以什么样的形式存在的 回答要点: 主要从以下几点去考虑, ...
- [Java] 类库例题
例1 字符串操作 定义一个StringBuffer类对象,然后通过append()方法向对象中添加26个小写字母,每次只添加一次,共添加26次,然后按逆序方式输出,并且可以删除前5个字符 面向过程实现 ...
- docker部署harbor私有镜像库(3)
一.harbor介绍 在实际生产运维中,往往需要把镜像发布到几十.上百台或更多的节点上.这时单台Docker主机上镜像已无法满足,项目越来越多,镜像就越来越多,都放到一台Docker主机上是不行的,我 ...
- linux 详解useradd 命令基本用法
linux 详解useradd 命令基本用法 时间:2019-03-24 本文章向大家介绍linux 详解useradd 命令基本用法,主要包括linux 详解useradd 命令基本用法使用实例.应 ...