使用Boost序列化和反序列化JSON
Serializing and deserializing JSON with Boost
我是C++新手。使用boost
序列化和反序列化std::Map
类型的数据的最简单方法是什么。我发现了一些使用PropertyTree
的例子,但它们对我来说很模糊。
请注意,property_tree
将键解释为路径,例如,放置对"a.b"="z"将创建一个{"a":{"b":"z"}}JSON,而不是{"a.b":"z"}。否则,使用property_tree
是微不足道的。这里有一个小例子。
#include <sstream>
#include <map>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
using boost::property_tree::ptree;
using boost::property_tree::read_json;
using boost::property_tree::write_json;
void example() {
// Write json.
ptree pt;
pt.put ("foo", "bar");
std::ostringstream buf;
write_json (buf, pt, false);
std::string json = buf.str(); // {"foo":"bar"}
// Read json.
ptree pt2;
std::istringstream is (json);
read_json (is, pt2);
std::string foo = pt2.get<std::string> ("foo");
}
std::string map2json (const std::map<std::string, std::string>& map) {
ptree pt;
for (auto& entry: map)
pt.put (entry.first, entry.second);
std::ostringstream buf;
write_json (buf, pt, false);
return buf.str();
}
Boost 1.75及更高版本现在有了一个强大的本地JSON库:
https://www.boost.org/doc/libs/develop/libs/json/doc/html/index.html
我不建议使用Boost。PropertyTree的JSON算法不再存在,因为它们不完全符合规范
一些公司要求我实现JSON序列化库,它比boost lib更快。我做到了——它比提升lib快了大约10倍。我为任何人发布代码使用
#pragma once
#include <string>
#include <vector>
#include <regex>
#include <fstream>
enum class JsonNodeType { Array, Object, String };
class JsonNode
{
JsonNodeType m_nodeType;
std::vector<JsonNode*>* m_values{0};
std::vector<std::string>* m_keys{0};
std::string m_value{};
inline static int m_indent;
inline static bool m_formatOutput;
const int m_indentInc{4};
public:
JsonNode(JsonNodeType type)
{
m_nodeType = type;
switch (m_nodeType) {
case JsonNodeType::Object: m_keys = new std::vector<std::string>();
[[fallthrough]];
case JsonNodeType::Array: m_values = new std::vector<JsonNode*>();
}
};
JsonNode(std::string value)
{
m_nodeType = JsonNodeType::String;
m_value = value;
}
~JsonNode()
{
if (m_values)
for (JsonNode* node : *m_values)
delete node;
delete m_values;
delete m_keys;
}
void Add(JsonNode* node)
{
assert(m_nodeType == JsonNodeType::Array);
m_values->push_back(node);
}
void Add(const char* key, JsonNode* node)
{
assert(m_nodeType == JsonNodeType::Object);
m_values->push_back(node);
m_keys->push_back(key);
}
void Add(const char* key, std::string value)
{
assert(m_nodeType == JsonNodeType::Object);
m_keys->push_back(key);
m_values->push_back(new JsonNode(value));
}
void Add(std::string value)
{
assert(m_nodeType == JsonNodeType::Array);
m_values->push_back(new JsonNode(value));
}
void Add(int value)
{
assert(m_nodeType == JsonNodeType::Array);
m_values->push_back(new JsonNode(std::to_string(value)));
}
void Add(const char* key, bool value)
{
assert(m_nodeType == JsonNodeType::Object);
m_keys->push_back(key);
m_values->push_back(new JsonNode(value ? "true" : "false"));
}
void OutputToStream(std::ostream& ofs, bool formatOutput = true)
{
m_indent = 0;
m_formatOutput = formatOutput;
OutputNodeToStream(ofs);
ofs << std::endl;
}
std::string EscapeString(std::string& str)
{
std::regex html2json("\\|\/|\"");
std::regex newline("n");
std::string tmp = std::regex_replace(str, html2json, "\$&");
return std::regex_replace(tmp, newline, "\n");
}
private:
void OutputNodeToStream(std::ostream& ofs)
{
switch (m_nodeType) {
case JsonNodeType::String:
ofs << """ << m_value << """;
break;
case JsonNodeType::Object:
OutputObjectToStream(ofs);
break;
case JsonNodeType::Array:
OutputArrayToStream(ofs);
break;
}
}
void ChangeIndent(std::ostream& ofs, int indentDelta)
{
if (!m_formatOutput)
return;
m_indent += indentDelta;
ofs << std::endl;
}
void OutputIndents(std::ostream& ofs)
{
if (!m_formatOutput)
return;
for (int i = 0; i < m_indent; i++)
ofs << " ";
}
void OutputObjectToStream(std::ostream& ofs)
{
assert(m_nodeType == JsonNodeType::Object);
assert(m_keys->size() == m_values->size());
if (m_keys->empty())
{
ofs << """";
return;
}
ofs << "{";
ChangeIndent(ofs, m_indentInc);
for (int i = 0; i < m_keys->size(); i++)
{
if (i > 0)
ofs << ",";
if (i > 0 && m_formatOutput)
ofs << std::endl;
OutputIndents(ofs);
ofs << """ << m_keys->at(i) << "": ";
m_values->at(i)->OutputNodeToStream(ofs);
}
ChangeIndent(ofs, -m_indentInc);
OutputIndents(ofs);
ofs << "}";
}
void OutputArrayToStream(std::ostream& ofs)
{
assert(m_nodeType == JsonNodeType::Array);
if (m_values->empty())
{
ofs << """";
return;
}
ofs << "[";
ChangeIndent(ofs, m_indentInc);
for (int i = 0; i < m_values->size(); i++)
{
if (i > 0)
ofs << ",";
if(i > 0 && m_formatOutput)
ofs << std::endl;
OutputIndents(ofs);
m_values->at(i)->OutputNodeToStream(ofs);
}
ChangeIndent(ofs, -m_indentInc);
OutputIndents(ofs);
ofs << "]";
}
};
的使用示例
创建json树:
JsonNode* Circuit::GetMyJson()
{
JsonNode* node = new JsonNode(JsonNodeType::Object);
JsonNode* gates = new JsonNode(JsonNodeType::Array);
for (auto& [k, v] : m_gates)
gates->Add(v.GetMyJson());
node->Add("gates", gates);
return node;
}
输出树:
std::unique_ptr<JsonNode> node (simulation->GetMyJson());
std::ofstream output("output.json", std::ios::out);
node->OutputToStream(output);
相关文章:
- 如何知道QDataStream不能反序列化某些内容
- 增强基于 XML class_id的反序列化
- 提升反序列化对象具有 nan 或 -nan 值
- 如何在 c++ 非托管代码中反序列化 byte[] 的 json 字符串?
- 如何反序列化数组?
- Protobuf中重复字段的问题.使用重复字段进行序列化/反序列化的更好方法是什么?
- 通过 tcp 发送 C# 类并在 C++ 上反序列化
- 序列化和反序列化boost共享指针
- 在C++中使用POCO和grain对多个对象进行反序列化
- 使用 Json 转换器反序列化 WCF 服务中的C++字符串
- 我可以将平面缓冲区序列化/反序列化到 JSON 中/从 JSON 序列化吗?
- 使用 Cereal 反序列化 JSON 字符串
- Cpp:Cpp中的JSON解析器,提供支持序列化/反序列化功能,将JSON对象转换为用户定义的类
- 在 c++ 中使用 Json 序列化/反序列化字节数组
- 使用Boost序列化和反序列化JSON
- 如何在不使用任何第三方库的情况下在 c++ 中反序列化 json 字符串
- C++json反序列化程序
- JSON反序列化C++
- 我可以用C++从协议缓冲区序列化/反序列化JSON吗
- 如何使用Poco c++库从JSON反序列化std::map