You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Src/nmNum/nmData/nmDataJsonTools.cpp

254 lines
8.6 KiB
C++

#include "nmDataJsonTools.h"
#include <QVariant>
#include <QVariantList> // 确保包含这些,以防万一
#include <QVariantMap>
#include <QDebug> // 用于调试输出
// RapidJSON 内部使用 char*,这里需要转换为 std::string
#include <string>
#include <QFile>
#include <QTextStream>
#include <QString>
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/prettywriter.h" // For pretty printing JSON
#include "rapidjson/stringbuffer.h"
using namespace rapidjson;
// 辅助函数:将 QVariant 递归转换为 rapidjson::Value
// 这是最重要的部分,因为它将处理 QVariant 中的嵌套结构
rapidjson::Value QVariantToRapidjsonValue(const QVariant& qv, rapidjson::Document::AllocatorType& allocator) {
if (qv.type() == QVariant::Int) {
return rapidjson::Value(qv.toInt());
} else if (qv.type() == QVariant::Double) {
return rapidjson::Value(qv.toDouble());
} else if (qv.type() == QVariant::String) {
return rapidjson::Value(qv.toString().toStdString().c_str(), allocator);
} else if (qv.type() == QVariant::Bool) {
return rapidjson::Value(qv.toBool());
} else if (qv.type() == QVariant::List) {
rapidjson::Value arr(rapidjson::kArrayType);
QVariantList list = qv.toList();
for (int i = 0; i < list.size(); ++i) {
arr.PushBack(QVariantToRapidjsonValue(list.at(i), allocator), allocator);
}
return arr;
} else if (qv.type() == QVariant::Map) {
rapidjson::Value obj(rapidjson::kObjectType);
QVariantMap map = qv.toMap();
// Qt4 QMapIterator
QMapIterator<QString, QVariant> i(map);
while (i.hasNext()) {
i.next();
rapidjson::Value key(i.key().toStdString().c_str(), allocator);
obj.AddMember(key, QVariantToRapidjsonValue(i.value(), allocator), allocator);
}
return obj;
} else if (qv.isNull() || qv.type() == QVariant::Invalid) {
return rapidjson::Value(rapidjson::kNullType);
}
// 默认情况或不支持的类型
qDebug() << "Warning: Unsupported QVariant type in QVariantToRapidjsonValue: " << qv.type();
return rapidjson::Value(rapidjson::kNullType);
}
// 写入json
void nmDataJsonTools::jsonAdd(rapidjson::Document& document,
QVariant value, QVector<QVariant> path) {
Document::AllocatorType& allocator = document.GetAllocator();
Value* current = &document;
for (int i = 0; i < path.size(); ++i) {
QVariant key_var = path.at(i);
// 如果是最后一层路径,设置值
if (i == path.size() - 1) {
if (key_var.type() == QVariant::String) {
std::string key_str = key_var.toString().toStdString();
const char* key_c_str = key_str.c_str();
// 确保当前节点是对象,以便添加成员
if (!current->IsObject()) {
current->SetObject(); // 这一步至关重要,如果 current 不是对象,就把它变成对象
}
// 将 QVariant 转换为 rapidjson::Value
rapidjson::Value val_to_add = QVariantToRapidjsonValue(value, allocator);
if (current->HasMember(key_c_str)) {
// 如果存在,替换值
(*current)[key_c_str].CopyFrom(val_to_add, allocator);
} else {
// 如果不存在,添加新成员
current->AddMember(rapidjson::Value(key_c_str, allocator), val_to_add, allocator);
}
} else if (key_var.type() == QVariant::Int) { // 最后一层路径是数组索引
int index = key_var.toInt();
if (!current->IsArray()) {
current->SetArray(); // 如果当前不是数组,就把它变成数组
}
// 确保数组大小足够
while (current->Size() <= index) {
current->PushBack(rapidjson::Value(rapidjson::kNullType), allocator); // 用 null 填充
}
// 将 QVariant 转换为 rapidjson::Value
rapidjson::Value val_to_add = QVariantToRapidjsonValue(value, allocator);
(*current)[index].CopyFrom(val_to_add, allocator);
} else {
qDebug() << "Error: Invalid path component type at end of path (expected string or int).";
}
return; // 最后一层路径处理完毕
}
// 处理中间路径节点
if (key_var.type() == QVariant::String) {
std::string key_str = key_var.toString().toStdString();
const char* key_c_str = key_str.c_str();
if (!current->IsObject()) {
current->SetObject(); // 确保当前节点是对象
}
if (!current->HasMember(key_c_str)) {
// 如果中间路径节点不存在,则创建新的空对象
current->AddMember(rapidjson::Value(key_c_str, allocator), rapidjson::Value(rapidjson::kObjectType).Move(), allocator);
}
current = &((*current)[key_c_str]); // 移动到下一级
} else if (key_var.type() == QVariant::Int) {
int index = key_var.toInt();
if (!current->IsArray()) {
current->SetArray(); // 确保当前节点是数组
}
// 确保数组大小足够
while (current->Size() <= index) {
current->PushBack(rapidjson::Value(rapidjson::kNullType), allocator); // 用 null 填充
}
// 检查目标索引处是否是对象或数组。如果不是,就把它变成对象
if (!(*current)[index].IsObject() && !(*current)[index].IsArray()) {
(*current)[index].SetObject(); // 默认创建对象,如果需要数组则再处理
}
current = &((*current)[index]); // 移动到下一级
} else {
qDebug() << "Error: Invalid path component type in jsonAdd (expected string or int).";
return; // 路径不合法,提前退出
}
}
}
// 辅助函数:将 rapidjson::Value 递归转换为 QVariant
QVariant RapidjsonValueToQVariant(const rapidjson::Value& rv) {
if (rv.IsInt()) {
return QVariant(rv.GetInt());
} else if (rv.IsDouble()) {
return QVariant(rv.GetDouble());
} else if (rv.IsString()) {
return QVariant(rv.GetString());
} else if (rv.IsBool()) {
return QVariant(rv.GetBool());
} else if (rv.IsArray()) {
QVariantList list;
for (rapidjson::SizeType i = 0; i < rv.Size(); ++i) {
list.append(RapidjsonValueToQVariant(rv[i]));
}
return list;
} else if (rv.IsObject()) {
QVariantMap map;
for (rapidjson::Value::ConstMemberIterator itr = rv.MemberBegin(); itr != rv.MemberEnd(); ++itr) {
map.insert(itr->name.GetString(), RapidjsonValueToQVariant(itr->value));
}
return map;
} else if (rv.IsNull()) {
return QVariant(); // QVariant() 表示null
}
// 未知类型或默认处理
qDebug() << "Warning: Unsupported rapidjson::Value type in RapidjsonValueToQVariant: " << rv.GetType();
return QVariant();
}
// 读json
void nmDataJsonTools::jsonRead(rapidjson::Document &document, QVariant &value, QVector<QVariant> path) {
const rapidjson::Value* current = &document;
for (int i = 0; i < path.size(); ++i) {
QVariant key_var = path.at(i);
if (key_var.type() == QVariant::String) {
std::string key_str = key_var.toString().toStdString();
const char* key_c_str = key_str.c_str();
if (current->IsObject() && current->HasMember(key_c_str)) {
current = &((*current)[key_c_str]);
} else {
value = QVariant(); // 路径不存在
return;
}
} else if (key_var.type() == QVariant::Int) {
int index = key_var.toInt();
if (current->IsArray() && index >= 0 && index < current->Size()) {
current = &((*current)[index]);
} else {
value = QVariant(); // 索引无效
return;
}
} else {
value = QVariant(); // 无效路径组件
return;
}
}
// 到达路径的末端将当前值赋给value
value = RapidjsonValueToQVariant(*current);
}
// 将 RapidJSON Document 写入文件
bool nmDataJsonTools::WriteDomToFile(const rapidjson::Document& doc, const QString& filePath)
{
// 将 RapidJSON Document 转换为字符串
rapidjson::StringBuffer buffer;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer); // 使用 PrettyWriter 进行美化输出
doc.Accept(writer);
// 将字符串写入文件
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qDebug() << "Error: Could not open file for writing:" << filePath;
return false;
}
QTextStream out(&file);
out << buffer.GetString();
file.close();
return true;
}
// 从文件读取 JSON 并解析到 RapidJSON Document
bool nmDataJsonTools::ReadDomFromFile(const QString& filePath, rapidjson::Document& doc)
{
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "Error: Could not open file for reading:" << filePath;
return false;
}
QTextStream in(&file);
QString jsonString = in.readAll();
file.close();
// 将 QString 转换为 std::string
QByteArray byteArray = jsonString.toUtf8();
std::string stdJsonString = byteArray.constData();
// 解析 JSON 字符串到 RapidJSON Document
doc.Parse(stdJsonString.c_str());
if (doc.HasParseError()) {
qDebug() << "Error parsing JSON from file:" << filePath << "Error:" << doc.GetParseError();
return false;
}
return true;
}