Cpp:Cpp中的JSON解析器,提供支持序列化/反序列化功能,将JSON对象转换为用户定义的类



我正在进行原生C++开发,并寻找能够处理复杂JSON文件并转换为类对象的JSON解析器。

  1. 我查看了C++中提供的JSON解析器的本机基准测试,得出的结论是,考虑到处理时间和大小处理,RapidJSON很受欢迎,最适合。

  2. 我的要求是将JSON对象转换为用户定义的类,反之亦然。

  3. Jackson具有Objectmapper类,该类提供了读取和写入JSON的功能,可以是向基本POJO(普通旧Java对象)读取和写入,也可以是向通用JSON树模型(JsonNode)读取和从通用JSON树模式读取和写入。

问题:

  1. RapidJSON或其他JSON解析器中是否有等效的功能允许我们配置序列化和反序列化功能(例如:Jackson JAVA库是高度可定制的序列化和反串行化过程,将JSON对象转换为JAVA类)
  2. 如果没有,解决问题的正确方法是什么?有没有唯一的方法可以构建自己的序列化程序来转换为我们的自定义类

注意:我在stackoverflow上看了一些帖子,但没有找到一个能回答它的。

RapidJSON或其他JSON解析器中是否有类似的东西允许我们配置序列化和反序列化功能(例如:Jackson JAVA库是高度可定制的序列化和反串行化过程,将JSON对象转换为JAVA类)?

我认为ThorsSerializer做了这项工作
您所要做的就是通过ThorsAnvil_MakeTrait()声明类中哪些字段是可序列化的(请参见下文)。

如果没有,解决它的正确方法是什么?有没有唯一的方法可以构建自己的序列化程序来转换为我们的自定义类?

您可以使用RapidJSON(或其他几个库),但您需要编写客户代码,将库生成的JSON对象转换为您自己的对象。这并不难。

大多数库的另一个缺点是,它们实际上在类似JSON的对象中构建了数据的完整表示,并且您需要将数据复制到您的结构中。对于小物体来说不是问题,但对于更复杂的结构来说,这可能会占用一些空间。ThorsSerializer完全避免了这种情况,并将数据直接复制到您的结构中:请参阅查看使用的内存。

使用与@Daniel相同的示例
使用ThorsSerializer:https://github.com/Loki-Astari/ThorsSerializer
注:我是作者。

#include <string>
const std::string s = R"(
[
{
"author" : "Haruki Murakami",
"title" : "Kafka on the Shore",
"price" : 25.17
},
{
"author" : "Charles Bukowski",
"title" : "Pulp",
"price" : 22.48
}
]
)";
namespace ns {
struct book
{   
std::string author;
std::string title;
double price;
};  
} // namespace ns

#include <iostream>
#include "ThorSerialize/Traits.h"   // for ThorsAnvil_MakeTrait
#include "ThorSerialize/SerUtil.h"  // Has definitions for all STL types.
#include "ThorSerialize/JsonThor.h" // JSON version: There is also YAML

ThorsAnvil_MakeTrait(ns::book, author, title, price);

那么在main中读/写json很简单:

int main()
{
using ThorsAnvil::Serialize::jsonExport;
using ThorsAnvil::Serialize::jsonImport;

std::stringstream   stream(s);
ns::book                   book;
std::vector<ns::book>      allBooks;
stream >> jsonImport(allBooks);
std::cout << jsonExport(allBooks)
<< "nn"
<< jsonExport(allBooks, ThorsAnvil::Serialize::PrinterInterface::OutputType::Stream)
<< "nn";
}

构建:

> g++ -std=c++14 main.cpp -lThorSerialize17

输出:

> ./a.out 
[ 
{ 
"author": "Haruki Murakami", 
"title": "Kafka on the Shore", 
"price": 25.17
}, 
{ 
"author": "Charles Bukowski", 
"title": "Pulp", 
"price": 22.48
}]
[{"author":"Haruki Murakami","title":"Kafka on the Shore","price":25.17},{"author":"Charles Bukowski","title":"Pulp","price":22.48}]

jsoncons、nlohmann和ThorsSerializer都支持JSON和C++对象之间的转换。jsoncons和nlohmann的例子如下所示,Martin York在另一篇帖子中为他的ThorsSerializer提供了一个例子。在我看来,后者非常好,当然也因简洁而获奖。本着奥斯卡·王尔德的名言"模仿是最真诚的奉承"的精神,我向JSONCONS介绍了宏JSONCONS_ALL_MEMBER_TRAITS,并对该示例进行了相应的修改。

考虑

const std::string s = R"(
[
{
"author" : "Haruki Murakami",
"title" : "Kafka on the Shore",
"price" : 25.17
},
{
"author" : "Charles Bukowski",
"title" : "Pulp",
"price" : 22.48
}
]
)";
namespace ns {
struct book
{
std::string author;
std::string title;
double price;
};
} // namespace ns

使用jsoncons在sstd::vector<ns::book>:之间转换

#include <jsoncons/json.hpp>
namespace jc = jsoncons;
// Declare the traits. Specify which data members need to be serialized.
JSONCONS_ALL_MEMBER_TRAITS(ns::book,author,title,price);
int main()
{
std::vector<ns::book> book_list = jc::decode_json<std::vector<ns::book>>(s);
std::cout << "(1)n";
for (const auto& item : book_list)
{
std::cout << item.author << ", " 
<< item.title << ", " 
<< item.price << "n";
}
std::cout << "n(2)n";
jc::encode_json(book_list, std::cout, jc::indenting::indent);
std::cout << "nn";
}

输出:

(1)
Haruki Murakami, Kafka on the Shore, 25.17
Charles Bukowski, Pulp, 22.48
(2)
[
{
"author": "Haruki Murakami",
"price": 25.17,
"title": "Kafka on the Shore"
},
{
"author": "Charles Bukowski",
"price": 22.48,
"title": "Pulp"
}
]

使用nlohmann在sstd::vector<ns::book>:之间进行转换

#include <nlohmann/json.hpp>
#include <iomanip>
namespace nh = nlohmann;
// Provide from_json and to_json functions in the same namespace as your type   
namespace ns {
void from_json(const nh::json& j, ns::book& val) 
{
j.at("author").get_to(val.author);
j.at("title").get_to(val.title);
j.at("price").get_to(val.price);
}
void to_json(nh::json& j, const ns::book& val) 
{
j["author"] = val.author;
j["title"] = val.title;
j["price"] = val.price;
}
} // namespace ns
int main()
{
nh::json j = nh::json::parse(s);
std::vector<ns::book> book_list = j.get<std::vector<ns::book>>();
std::cout << "n(1)n";
for (const auto& item : book_list)
{
std::cout << item.author << ", " 
<< item.title << ", " 
<< item.price << "n";
}
std::cout << "n(2)n";
nh::json j2 = book_list;
std::cout << std::setw(4) << j2 << "nn";
}

输出:

(1)
Haruki Murakami, Kafka on the Shore, 25.17
Charles Bukowski, Pulp, 22.48
(2)
[
{
"author": "Haruki Murakami",
"price": 25.17,
"title": "Kafka on the Shore"
},
{
"author": "Charles Bukowski",
"price": 22.48,
"title": "Pulp"
}
]

我最近发布了一个名为json-cpp-gen的新工具。它解析您提供的C++结构(目前不是类,因为它们往往具有私有数据),并自动为这些结构生成高效的JSON解析器和序列化程序(作为C++代码)。我相信这可能正是你想要的。

最新更新