json解析之C++库nlohmannjson
项⽬地址:
设计⽬标
直观的语法。在像这样的语⾔中,JSON就像是⼀个⼀流的数据类型。我们使⽤了现代C++的所有操作符魔法,在您的代码中实现了相同的感觉。查看以下⽰例你会明⽩我的意思。
琐碎的集成。我们的整个代码由⼀个单独的头⽂件组成json.hpp。就这样。没有库,没有⼦项⽬,没有依赖,没有复杂的构建系统。这个类是⽤普通的C++11编写的。总之,⼀切都不需要调整你的编译器标志或项⽬设置。
严格的测试。我们的类经过包含100%的单元测试,包括所有异常⾏为。此外,我们与Valgrind还有xxx确认没有内存泄漏。⾕歌OSS-模糊此外,对所有解析器24/7运⾏模糊测试,迄今为⽌⾼效地执⾏了数⼗亿次测试。为了保持⾼质量,该项⽬遵循(CII)最佳实践。
还有⼀些其他⽅⾯对我们来说并不重要:
内存效率。每个JSON对象都有⼀个指针(联合的最⼤⼤⼩)和⼀个枚举元素(1字节)的开销。默认泛化使⽤以下C++数据类
型:std::string对应字符串,int64_t,uint64_t或者double对应数字,std::map对于对象object,std::vector对应数组,以及bool对应布尔值。但是,您可以模板化通⽤类basic_json满⾜你的需求。
速度。肯定有更快的JSON库在外⾯。但是,如果您的⽬标是通过添加带有单个头⽂件的JSON⽀持来加快开发速度,那么这个库就是您的不⼆之选。
Integration
json.hpp 唯⼀需要的⽂件。 只需要添加
#include <nlohmann/json.hpp>
// for convenience
using json = nlohmann::json;
你想要处理json的⽂件中,并且设置⽀持C++即可。
您可以进⼀步使⽤⽂件include/nlohmann/json_fwd.hpp⽤于转发声明。json_fwd.hpp的安装(作为cmake安装步骤的⼀部分)可以通过设置-DJSON _ MultipleHeaders =ON
json值的类型有哪些
例⼦
除了下⾯的⽰例,您可能还想查看⽂档,其中每个函数包含⼀个单独的代码⽰例(例如,查看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
}
}
可以这样写:
// 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}
}}
};
请注意,在所有这些情况下,您永远不需要“告诉”编译器您想要使⽤哪个JSON值类型。如果你想明确或表达⼀些边缘情况,函数 json::array() 和 json::object()会有帮助,如下:
// a way to express the empty array []
json empty_array_explicit = json::array();
// ways to express the empty object {}
json empty_object_implicit = json({});
json empty_object_explicit = json::object();
// a way to express an _array_ of key/value pairs [["currency", "USD"], ["value", 42.99]]
json array_not_object = json::array({ {"currency", "USD"}, {"value", 42.99} });
序列化/反序列化
To/from strings
您可以通过添加_json到⼀个字符串,来创建⼀个JSON值(反序列化):
// 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;
请注意,如果不附加_json后缀,传递的字符串⽂字不会被解析,⽽只是⽤作JSON字符串值。也就是说,json j = "{ \"happy\": true, \"pi\": 3.141 }"只会存储字符串 "{ \"happy\": true, \"pi\": 3.141 }",⽽不是解析实际的对象。
上⾯的例⼦也可以⽤json::parse():
// parse explicitly
auto j3 = json::parse("{ \"happy\": true, \"pi\": 3.141 }");
序列化
你也可以得到⼀个json对象对应的的字符串表达式(序列化):
// 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
// }
如上所⽰,dump添加参数,可以使得打印结果更美观。
请注意序列化和赋值之间的区别:
// store a string in a JSON value
json j_string = "this is a string";
// 在json类中存储⼀个字符串
// retrieve the string value
// 获取内部的字符串的值
auto cpp_string = <std::string>();
// retrieve the string value (alternative when an variable already exists)
std::string cpp_string2;
_to(cpp_string2);
// 将内部的字符串的值赋给cpp_string2?
/
/ retrieve the serialized value (explicit JSON serialization)
// 显式的将json对象序列化为std::string
std::string serialized_string = j_string.dump();
// output of original string
// 输出:获取内部的字符串的值、通过json对象赋给字符串的值、直接从json获取内部字符串的值
std::cout << cpp_string << " == " << cpp_string2 << " == " << <std::string>() << '\n';
// output of serialized value
// 重载了cout操作符,直接输出json对象的值
std::cout << j_string << " == " << serialized_string << std::endl;
第⼀个,是在json类中存储⼀个字符串
第⼆个,是获取内部字符串的值。
json对象重载了cout操作符。
.dump()总是返回序列化值,并且。.get<std::string>()返回最初存储的字符串值。
注意
该库仅⽀持UTF-8。当您在库中存储不同编码的字符串时,调⽤.dump()可能会引发异常,除⾮json::error_handler_t::replace或者json::error_handler_t::ignore被使⽤。
Note the library only supports UTF-8. When you store strings with
different encodings in the library, calling dump() may throw an
exception unless json::error_handler_t::replace or
json::error_handler_t::ignore are used as error handlers.
To/from streams (e.g. files, string streams)
也可以使⽤stream来序列化和反序列化:
// deserialize from standard input
json j;
std::cin >> j;
// serialize to standard output
std::cout << j;
// the setw manipulator was overloaded to set the indentation for pretty printing
std::cout << std::setw(4) << j << std::endl;
setw()操作符被重载过,可以通过它来设置缩进和更nice的打印格式。
这些运算符适⽤于std::istream或者std::ostream的任何⼦类。以下是⽂件的⼀些⽰例:
// read a JSON file
// 通过⽂件流得到json对象
std::ifstream i("file.json");
json j;
i >> j;
// write prettified JSON to another file
// 将json对象nice的写⼊到⽂件中
std::ofstream o("pretty.json");
o << std::setw(4) << j << std::endl;
请注意,如果将 异常位 设置为failbit,则不适合这个⽤例。这将导致程序终⽌,原因是noexcept说明符正在使⽤。
Please note that setting the exception bit for failbit is inappropriate for this use case. It will result in program
termination due to the noexcept specifier in use.
Read from iterator range
通过范围迭代器来解析。
也可以从迭代器范围解析JSON也就是说,来⾃迭代器可访问的任何容器,值类型是1、2或4字节的整数类型,将分别解释为UTF-8、UTF-16和UTF-32。例如,⼀个std::vector<std::uint8_t>或者std::vector<std::uint16_t>:
std::vector<std::uint8_t> v = {'t', 'r', 'u', 'e'};
json j = json::parse(v.begin(), v.end());
You may leave the iterators for the range [begin, end):
std::vector<std::uint8_t> v = {'t', 'r', 'u', 'e'};
json j = json::parse(v);
类似于STL的访问(STL-like access)
我们将JSON类设计成⾏为就像STL容器⼀样。事实上,它满⾜了可逆容器要求。
添加元素:
// create an array using push_back
json j;
j.push_back("foo");
j.push_back(1);
j.push_back(true);
// also use emplace_back
迭代器遍历:
// iterate the array
for (json::iterator it = j.begin(); it != j.end(); ++it) {
std::cout << *it << '\n';
}
// range-based for
for (auto& element : j) {
std::cout << element << '\n';
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论