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++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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;
}