当前位置: 首页 > news >正文

JSON与EXL文件互转

功能:实现json到excel文件的相互转换(支持json多选版)

目的:编码与语言对应,方便大家使用

页面设计:

介绍:

1.选择文件栏目选择想要转换的文件

2.生成路径是转换后文件所在目录

3.小方框勾选与不勾选分别代表exl到json和json到exl两种类型的转换

使用方法:

1.点击选择按钮,选择要解析的文件(json转exl支持多选文件,按ctrl或shift键)

  1. 同样选择一个生成的路径,点击转换按钮。不选路径则会弹出错误提示。

3.点击exl转json复选框,则会清除之前所选的json文件,切换能够所选的文件类型

4.选好所需转换的文件和和生成路径,点击转换按钮。转换完成后会弹出提示框。

5.找到目录下转换好的文件并打开查看。

(1)单个json转exl,生成文件为json文件的原名字。多选转换名字为JsonToExl。

(2)转换后第一行第一列固定为key,第一行其他列标题对应的各个json文件名字。

(3)多转情况下,有的文件中没有key其对应内容,则填充为Null值。(下图1)

(4)若转换的json文件中包含多层json对象,每层添加标识符“#¥&”(下图3)

6.excel转json也是同理,勾上对钩,选择要转换的excel文件,点击转换。根据exl中的首行标题名,生成的json文件名

 原代码:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "qfiledialog.h"
#include <QDebug>
#include <QtWidgets/QMessageBox>
#include <QCoreApplication>
#include <qprogressbar.h>
#include <QProgressDialog.h>
#include <QMetaType>
MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);ui->progressBar->hide();ui->version->setText(APP_VERSION);workThread = new QThread;ConvertWork = new ConvertThread;ConvertWork->moveToThread(workThread);qRegisterMetaType<eConvertType>("eConvertType");//需注册 参数含有枚举类型,否则将无法进入槽函数connect(ConvertWork, &ConvertThread::Sig_Result, this, &MainWindow::on_Progress);connect(this, &MainWindow::Sig_SetConvert, ConvertWork, &ConvertThread::setConvert);
}MainWindow::~MainWindow()
{workThread->quit();ConvertWork->deleteLater();workThread->deleteLater();delete ui;
}//转换按钮点击
void MainWindow::on_ConvertButton_clicked()
{if(ui->FileNameText->toPlainText().isEmpty()){QMessageBox *msgBox;msgBox = new QMessageBox("","请选择转换目标文件",QMessageBox::NoIcon,QMessageBox::Ok | QMessageBox::Default,NULL,0);msgBox->setWindowFlags(Qt::WindowStaysOnTopHint);msgBox->show();return;}if(ui->GeneratePathText->toPlainText().isEmpty()){QMessageBox *msgBox;msgBox = new QMessageBox("","请选择生成路径",QMessageBox::NoIcon,QMessageBox::Ok | QMessageBox::Default,NULL,0);msgBox->setWindowFlags(Qt::WindowStaysOnTopHint);msgBox->show();return;}if(!workThread->isRunning()){workThread->start();}if(ui->checkBox->isChecked()){emit Sig_SetConvert(emConvert_ExcelToJson, m_SelectFile, m_GeneratePath);}else{emit Sig_SetConvert(emConvert_JsonToExcel, m_SelectFile, m_GeneratePath);}
}//选择生成目录按钮点击
void MainWindow::on_GenerateButton_clicked()
{//选择文件路径m_GeneratePath = QFileDialog::getExistingDirectory();if(!m_GeneratePath.isEmpty()){//填入文本框ui->GeneratePathText->setText(m_GeneratePath);}
}//选择解析文件按钮点击
void MainWindow::on_SelectButton_clicked()
{m_SelectFile.clear();//选择要解析的文件if(ui->checkBox->isChecked()){//exl文件只做单选m_SelectFile.append(QFileDialog::getOpenFileName(this, tr("选择转码文件"), "/", "xls (*.xls)"));        }else{m_SelectFile = QFileDialog::getOpenFileNames(this, tr("选择转码文件"), "/", "json (*.json);;txt(*.txt)");}ui->FileNameText->clear();foreach (QString SelectFile, m_SelectFile){//填入文本框ui->FileNameText->append(SelectFile);}
}//复选框响应
void MainWindow::on_checkBox_clicked()
{if(ui->checkBox->isChecked()){if((ui->FileNameText->toPlainText().contains(".json")||ui->FileNameText->toPlainText().contains(".txt")))ui->FileNameText->clear();}else{if(ui->FileNameText->toPlainText().contains(".xls"))ui->FileNameText->clear();}
}void MainWindow::on_Progress(eConvertType ConvertType, int nProgress, const QString &strMsg)
{QString strConvertType = "";if (emConvert_JsonToExcel == ConvertType){strConvertType = "JsonToExcel";}else if (emConvert_ExcelToJson == ConvertType){strConvertType = "ExcelToJson";}if(100 == nProgress){ui->progressBar->hide();QMessageBox *msgBox;msgBox = new QMessageBox(strConvertType, strMsg, QMessageBox::NoIcon,QMessageBox::Ok|QMessageBox::Default, NULL, 0);msgBox->setWindowFlags(Qt::WindowStaysOnTopHint);msgBox->show();}else if(0 == nProgress){ui->progressBar->show();ui->progressBar->setOrientation(Qt::Horizontal);  // 水平方向ui->progressBar->setMinimum(0);  // 最小值ui->progressBar->setMaximum(0);  // 最大值}else{ui->progressBar->hide();QMessageBox *msgBox;msgBox = new QMessageBox(strConvertType, strMsg, QMessageBox::NoIcon,QMessageBox::Ok|QMessageBox::Default, NULL, 0);msgBox->setWindowFlags(Qt::WindowStaysOnTopHint);msgBox->show();}
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QThread>
#include "convertThread.h"namespace Ui {
class MainWindow;
}/**主页面**/
class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:void on_ConvertButton_clicked();//生成void on_SelectButton_clicked();//选择解析文件void on_GenerateButton_clicked();//选择生成路径void on_checkBox_clicked();//复选框void on_Progress(eConvertType ConvertType, int nProgress, const QString &strMsg);//进度条信号槽private:Ui::MainWindow *ui;QStringList m_SelectFile;//选择解析文件QString m_GeneratePath;//选择生成路径QThread *workThread;ConvertThread *ConvertWork;signals:void Sig_SetConvert(eConvertType ConvertType, const QStringList SelectFile, const QString GeneratePath);
};#endif // MAINWINDOW_H
#include "convertThread.h"
#include "qfiledialog.h"
#include <QDebug>
#include <QJsonParseError>
#include <ActiveQt/QAxObject>
#include <qjsonobject.h>
#include <qjsonarray.h>
#include <QDateTime>
ConvertThread::ConvertThread()
{m_eConvertType = emConvert_JsonToExcel;m_SelectFileList.clear();m_GeneratePath = "";m_Identifier = "#$&";m_BlankGrid = "";m_GenerateFileList.clear();m_NodeDataList.clear();
}ConvertThread::~ConvertThread()
{}void ConvertThread::setConvert(eConvertType ConvertType, const QStringList SelectFile, const QString GeneratePath)
{QMutexLocker locker(&lock);m_eConvertType = ConvertType;m_SelectFileList = SelectFile;m_GeneratePath = GeneratePath;m_NodeDataList.clear(); //清空m_GenerateFileList.clear();emit Sig_Result(m_eConvertType, 0, "start");if(m_eConvertType == emConvert_JsonToExcel){int FileOrder = 0;foreach (QString SelectFile, m_SelectFileList){//JSON转EXLif(analysisJson(SelectFile, FileOrder)==true){for(stNodeData &NodeData : m_NodeDataList){while(NodeData.m_value.size() <= FileOrder){NodeData.m_value.append(m_BlankGrid);}}FileOrder++;}else{return;}}addToExcel();}else if(m_eConvertType == emConvert_ExcelToJson){foreach (QString SelectFile, m_SelectFileList){//EXL转JSONbool result=analysisExcel(SelectFile);if(!result){return;}}addToJson();}
}//解析json字符
bool ConvertThread::analysisJson(QString FileName, int FileOrder)
{//采用普通方式打开文件,并且存入allDada中,注意这是一种QByteArray格式QFile loadFile(FileName);if(loadFile.open(QIODevice::ReadOnly)){//开始进行一系列JSON相关的处理        QByteArray allData = loadFile.readAll();//读取文件所有数据loadFile.close();//关闭文件QJsonParseError json_error;QJsonDocument::fromJson(allData, &json_error);//根据读取的数据检查json文件是否出错if(json_error.error != QJsonParseError::NoError){emit Sig_Result(m_eConvertType, -1, FileName + "文件解析出错");return false;}//顺序获取key值QString jsonString(allData);//将数据转为QStringbool ok;QVariantJsonList QVariantJsonList = QtJson::parse(jsonString, ok);if(QVariantJsonList.isEmpty()){emit Sig_Result(m_eConvertType, -1, FileName + "文件为空");return false;}foreach (stJsonNodeData JsonNodeData, QVariantJsonList){QList<stNodeData> NodeDataList = analysisValue(JsonNodeData.m_value, JsonNodeData.m_key, FileOrder);if(!NodeDataList.isEmpty())m_NodeDataList.append(NodeDataList);}/* key值自动排序 */
//        QJsonParseError json_error;}else{emit Sig_Result(m_eConvertType, -1, "Json文件打开失败");return false;}return true;
}//解析json节点
QList<stNodeData> ConvertThread::analysisValue(const QJsonValue OneValue, QString Key, int FileOrder)
{stNodeData team = {};QList<stNodeData> teamList = {};if(!OneValue.isObject()){for(stNodeData &NodeData : m_NodeDataList){if(NodeData.m_key == Key){while(NodeData.m_value.size() < FileOrder){NodeData.m_value.append(m_BlankGrid);}NodeData.m_value.append(OneValue.toString());return teamList;}}//里面没有再包一层直接添加数据team.m_key.append(Key);while(FileOrder > 0){team.m_value.append(m_BlankGrid);FileOrder--;}team.m_value.append(OneValue.toString());teamList.append(team);}else{// 转换成对象类型QJsonObject serialOneObj = OneValue.toObject();for(QJsonObject::iterator it = serialOneObj.begin(); it != serialOneObj.end(); ++it){team = {};//用#$&标识符区分每一层节点team.m_key = Key + m_Identifier +it.key();//根据value是否对象类型判断是否继续递归调研if(it.value().isObject()){QList<stNodeData> NodeDataList = analysisValue(it.value(), team.m_key, FileOrder);if(!NodeDataList.isEmpty())teamList.append(NodeDataList);}else{bool exist = false;for(stNodeData &NodeData : m_NodeDataList){if(NodeData.m_key == team.m_key){while(NodeData.m_value.size() < FileOrder){NodeData.m_value.append(m_BlankGrid);}NodeData.m_value.append(it.value().toString());exist = true;break;}}if(exist)continue;while(FileOrder > 0){team.m_value.append(m_BlankGrid);FileOrder--;}team.m_value.append(it.value().toString());teamList.append(team);}}}return teamList;
}QList<stNodeData> ConvertThread::analysisValue(const QVariant OneValue, QString Key, int FileOrder)
{stNodeData team = {};QList<stNodeData> teamList = {};QVariantJsonList JsonList = OneValue.value<QVariantJsonList>();if(JsonList.isEmpty()){for(stNodeData &NodeData : m_NodeDataList){if(NodeData.m_key == Key){while(NodeData.m_value.size() < FileOrder){NodeData.m_value.append(m_BlankGrid);}NodeData.m_value.append(OneValue.toString());return teamList;}}//里面没有再包一层直接添加数据team.m_key.append(Key);while(FileOrder > 0){team.m_value.append(m_BlankGrid);FileOrder--;}team.m_value.append(OneValue.toString());teamList.append(team);}else{// 转换成对象类型foreach (stJsonNodeData JsonNode, JsonList){team = {};//用#$&标识符区分每一层节点team.m_key = Key + m_Identifier + JsonNode.m_key;//根据value是否对象类型判断是否继续递归调研if(JsonNode.m_value.value<QVariantJsonList>().isEmpty()){bool exist = false;for(stNodeData &NodeData : m_NodeDataList){if(NodeData.m_key == team.m_key){while(NodeData.m_value.size() < FileOrder){NodeData.m_value.append(m_BlankGrid);}NodeData.m_value.append(JsonNode.m_value.toString());exist = true;break;}}if(exist)continue;while(FileOrder > 0){team.m_value.append(m_BlankGrid);FileOrder--;}team.m_value.append(JsonNode.m_value.toString());teamList.append(team);}else{QList<stNodeData> NodeDataList = analysisValue(JsonNode.m_value, team.m_key, FileOrder);if(!NodeDataList.isEmpty())teamList.append(NodeDataList);}}}return teamList;
}//添加到excel表格中
bool ConvertThread::addToExcel()
{  QAxObject *excel = new QAxObject(this);excel->setControl("Excel.Application");//连接Excel控件excel->dynamicCall("SetVisible (bool Visible)","false");//不显示窗体excel->setProperty("DisplayAlerts", false);//不显示任何警告信息。如果为true那么在关闭是会出现类似"文件已修改,是否保存"的提示QAxObject *workbooks = excel->querySubObject("WorkBooks");//获取工作簿集合workbooks->dynamicCall("Add");//新建一个工作簿QAxObject *workbook = excel->querySubObject("ActiveWorkBook");//获取当前工作簿QAxObject *worksheets = workbook->querySubObject("Sheets");//获取工作表集合QAxObject *worksheet = worksheets->querySubObject("Item(int)",1);//获取工作表集合的工作表1,即sheet1//宽度自适应auto range = worksheet->querySubObject("UsedRange");QAxObject * cells = range->querySubObject("Columns");if (cells){cells->dynamicCall("AutoFit");}//Json文件转换得到的列标题QList<QVariant> oRowdata;QList<QString> aline;aline.append("key");for (QString &SelectFile:m_SelectFileList){QStringList list = SelectFile.split("/");QString Title = list.last();if(Title.contains(".json"))Title.remove(".json");else if(Title.contains(".txt"))Title.remove(".txt");aline.append(Title);}oRowdata.append(QVariant(aline));char endCol = 'A' + m_SelectFileList.size();QString strRange = "A"+ QString::number(1) + ":" + QString(endCol) + QString::number(1);//需写入数据的表格范围QAxObject *oRange = worksheet->querySubObject("Range(QString)", strRange);if (oRange){oRange->setProperty("HorizontalAlignment", -4108);//设置单元格内容居中oRange->setProperty("NumberFormatLocal", "@");//设置单元格格式(文本)oRange->setProperty("Value2", oRowdata);//设置单元格值}//Key与对应内容oRowdata.clear();foreach (stNodeData NodeData, m_NodeDataList){aline.clear();aline.append(NodeData.m_key);foreach (QString value, NodeData.m_value){aline.append(value);}oRowdata.append(QVariant(aline));}QVariant oData(oRowdata);strRange = "A"+ QString::number(2) + ":" + QString(endCol) + QString::number(m_NodeDataList.size() + 1);oRange = worksheet->querySubObject("Range(QString)", strRange);if (oRange){oRange->setProperty("HorizontalAlignment", -4131);oRange->setProperty("NumberFormatLocal", "@");oRange->setProperty("Value2", oData);}QString filepath= m_SelectFileList.at(0);//单个json文件转excel,文件命名为源文件名字,多转一命名为JsonToExlif(m_SelectFileList.size()==1){QStringList list = m_SelectFileList.at(0).split("/");QString FileName =list.last();if(FileName.contains(".txt")){FileName=FileName.remove(".txt");}else if(FileName.contains(".json")){FileName=FileName.remove(".json");}filepath = m_GeneratePath+"\\" + FileName+".xls";}else if(m_SelectFileList.size()>1){filepath = m_GeneratePath + "\\JsonToExl.xls";}workbook->dynamicCall("SaveAs(const QString&)",QDir::toNativeSeparators(filepath));//保存至filepath,注意一定要用QDir::toNativeSeparators将路径中的"/"转换为"\",不然一定保存不了。workbook->dynamicCall("Close()");//关闭工作簿excel->dynamicCall("Quit()");//关闭exceldelete excel;excel = NULL;emit Sig_Result(m_eConvertType, 100, "转换完成");return true;
}//解析excel文件
bool ConvertThread::analysisExcel(QString FileName)
{QAxObject* excel = new QAxObject("Excel.Application");if (!excel) {emit Sig_Result(m_eConvertType, -1, "无法创建 Excel 对象");return false;}// 打开工作簿QAxObject* workbooks = excel->querySubObject("Workbooks");QAxObject* workbook = workbooks->querySubObject("Open(const QString&)", FileName);// 获取第一个工作表QAxObject* sheets = workbook->querySubObject("Worksheets");QAxObject* sheet = sheets->querySubObject("Item(int)", 1);QAxObject *rangeAx = sheet->querySubObject("UsedRange"); //直接读整个表QVariant rangeData = rangeAx ->dynamicCall("Value2()");QVariantList rangeDataList = rangeData.toList();bool first = true;foreach (QVariant rowData, rangeDataList){QVariantList rowDataList =  rowData.toList() ;stNodeData NodeData = {};for(int i = 0; i < rowDataList.size(); i++){QString cellValue = rowDataList[i].toString();if(0 == i)NodeData.m_key = cellValue;elseNodeData.m_value.append(cellValue);}if(first){first = false;m_GenerateFileList = NodeData.m_value;}else{m_NodeDataList.append(NodeData);}}// 关闭并释放资源workbook->dynamicCall("Close()");excel->dynamicCall("Quit()");delete sheet;delete sheets;delete workbook;delete workbooks;delete excel;excel = NULL;return true;
}//生成Json对象
void ConvertThread::generateValue(QJsonObject &pageObject, stNodeData NodeData, int FileOrder)
{//正数是从左到右切的字符串,从0开始,负数从右到左切,从-1开始   注意:数字代表字符串位置,不是字符位置!QString subStr1 = NodeData.m_key.section(m_Identifier, 0, 0);//取去除#$&后的第一段的字符内容QString subStr2 = NodeData.m_key.section(m_Identifier, 1, -1);//取去除#$&后得第2段到最后一段的内容if(!subStr1.isEmpty() && subStr2.isEmpty())//只有一层{if(NodeData.m_value.at(FileOrder) != m_BlankGrid)pageObject.insert(NodeData.m_key, NodeData.m_value.at(FileOrder));//直接插入对应的key,value}else if(!subStr2.isEmpty()){//判断是不是第一次添加这个结点stNodeData uNodeData = {subStr2, NodeData.m_value};//不含标识符的后半段结点数据for (int k = 0; k < pageObject.keys().size(); k++)//循环子对象所含的key的数量{if(subStr1 == pageObject.keys().at(k))//曾添加过该结点{QJsonObject uJsonObject = pageObject.value(subStr1).toObject();//根据字符找到对应的value值并将其转为object对象generateValue(uJsonObject, uNodeData, FileOrder);//递归pageObject[subStr1] = QJsonValue(uJsonObject);return;}}//str2不为空进行深层递归QJsonObject json;generateValue(json, uNodeData, FileOrder);pageObject.insert(subStr1, QJsonValue(json));}
}//生成Json串
void ConvertThread::generateValue(stJsonNodeData &JsonNode, stNodeData NodeData, int FileOrder)
{//正数是从左到右切的字符串,从0开始,负数从右到左切,从-1开始   注意:数字代表字符串位置,不是字符位置!QString subStr1 = NodeData.m_key.section(m_Identifier, 0, 0);//取去除#$&后的第一段的字符内容QString subStr2 = NodeData.m_key.section(m_Identifier, 1, -1);//取去除#$&后得第2段到最后一段的内容if(!subStr1.isEmpty() && subStr2.isEmpty())//只有一层{if(NodeData.m_value.at(FileOrder) != m_BlankGrid){stJsonNodeData Node = {};Node.m_key = NodeData.m_key;Node.m_value = NodeData.m_value.at(FileOrder);QVariantJsonList NodeList = JsonNode.m_value.value<QVariantJsonList>();NodeList.append(Node);JsonNode.m_value = QVariant::fromValue(NodeList);}}else if(!subStr2.isEmpty()){stNodeData uNodeData = {subStr2, NodeData.m_value};//不含标识符的后半段结点数据//判断是不是第一次添加这个结点QVariantJsonList JsonList = JsonNode.m_value.value<QVariantJsonList>();for(int i = 0; i < JsonList.size(); i++){if(subStr1 == JsonList[i].m_key){generateValue(JsonList[i], uNodeData, FileOrder);JsonNode.m_value = QVariant::fromValue(JsonList);QVariantJsonList aaa = JsonNode.m_value.value<QVariantJsonList>().at(i).m_value.value<QVariantJsonList>();return;}}stJsonNodeData Node = {};Node.m_key = subStr1;generateValue(Node, uNodeData, FileOrder);QVariantJsonList NodeList = JsonNode.m_value.value<QVariantJsonList>();NodeList.append(Node);JsonNode.m_value = QVariant::fromValue(NodeList);}
}QString ConvertThread::jsonDatatoString(stJsonNodeData JsonData, int level, bool last)
{QString jsonString;QString indentation;int i = level;while (i){indentation += "    ";i--;}jsonString += indentation;if(!JsonData.m_key.isEmpty()){jsonString += "\"" + JsonData.m_key + "\": ";}QVariantJsonList JsonNodeList = JsonData.m_value.value<QVariantJsonList>();if(JsonNodeList.isEmpty()){if(last)jsonString += "\"" + JsonData.m_value.toString() + "\"\n\n";elsejsonString += "\"" + JsonData.m_value.toString() + "\",\n";}else{QString NodeString;int count = 0;for(stJsonNodeData &NodeData : JsonNodeList){count++;if(count == JsonNodeList.size())NodeString += jsonDatatoString(NodeData, level + 1, true);elseNodeString += jsonDatatoString(NodeData, level + 1, false);}NodeString.chop(1);if(last)jsonString += "{\n" + NodeString + indentation + "}\n\n";elsejsonString += "{\n" + NodeString + indentation + "},\n";}return jsonString;
}//添加到json文件中
bool ConvertThread::addToJson()
{int FileOrder = 0;foreach (QString GenerateFile, m_GenerateFileList){/* 固定读取顺序 */stJsonNodeData JsonData;foreach (stNodeData NodeData, m_NodeDataList){generateValue(JsonData, NodeData, FileOrder);}QString jsonString = jsonDatatoString(JsonData);/* key值自动排序 */
//        QJsonObject pageObject;
//        foreach (stNodeData NodeData, m_NodeDataList)
//        {
//            generateValue(pageObject, NodeData, FileOrder);
//        }
//        QJsonDocument document;
//        document.setObject(pageObject);
//        QString jsonString = document.toJson(QJsonDocument::Indented);// 打开文件准备写入QString filePath = m_GeneratePath + "/" + GenerateFile + ".json";QFile file(filePath);if (!file.open(QIODevice::WriteOnly|QIODevice::Truncate)){emit Sig_Result(m_eConvertType, -1, "写入打开Json文件失败");return false;}// 写入文件file.write(jsonString.toUtf8());file.close();FileOrder++;}emit Sig_Result(m_eConvertType, 100, "转换完成");return true;
}
#ifndef CONVERTTHREAD_H
#define CONVERTTHREAD_H#include <QObject>
#include <QMutex>
#include <QMutexLocker>
#include "json.h"/**节点数据类型**/
struct stNodeData
{QString m_key;QList<QString> m_value;
};/**文件转换类型**/
enum eConvertType {emConvert_JsonToExcel = 0,emConvert_ExcelToJson =1
};/**文件转换线程**/
class ConvertThread : public QObject
{Q_OBJECTpublic:ConvertThread();~ConvertThread();    
public slots:void setConvert(eConvertType ConvertType, const QStringList SelectFile, const QString GeneratePath);private:bool analysisJson(QString FileName, int FileOrder);//解析jsonQList<stNodeData> analysisValue(const QJsonValue OneValue, QString Key, int FileOrder);//解析数据节点QList<stNodeData> analysisValue(const QVariant OneValue, QString Key, int FileOrder);//解析数据节点bool addToExcel();//生成EXL文件bool analysisExcel(QString FileName);//解析excelvoid generateValue(QJsonObject &pageObject, stNodeData NodeDataList, int FileOrder);//生成Json对象void generateValue(stJsonNodeData &JsonNodeList, stNodeData NodeDataList, int FileOrder);//生成Json串QString jsonDatatoString(stJsonNodeData JsonData, int level = 0, bool last = true);bool addToJson();//生成JSON文件private:eConvertType m_eConvertType;//转换类型QString m_BlankGrid;//空白格填充字符QStringList m_SelectFileList;//选择解析文件列表QString m_GeneratePath;//选择生成路径QString m_Identifier;//结点连接标识符QStringList m_GenerateFileList;//生成文件列表QList<stNodeData>  m_NodeDataList;//对象类型存储列表QMutex lock;signals:void Sig_Result(eConvertType ConvertType, int nProgress, const QString &strMsg);
};#endif // CONVERTTHREAD_H
#include <QDateTime>
#include <QStringList>
#include <QMetaType>
#include <qjsonobject.h>
#include "json.h"namespace QtJson {static QVariant parseValue(const QString &json, int &index, bool &success);static QVariant parseObject(const QString &json, int &index, bool &success);static QVariant parseArray(const QString &json, int &index, bool &success);static QVariant parseString(const QString &json, int &index, bool &success);static void eatWhitespace(const QString &json, int &index);static int lookAhead(const QString &json, int index);static int nextToken(const QString &json, int &index);/*** parse*/QVariantJsonList parse(const QString &json, bool &success) {success = true;QVariantJsonList JsonList;if (!json.isNull() || !json.isEmpty()) {QString data = json;int index = 0;QVariant Variant = parseValue(data, index, success);JsonList = Variant.value<QVariantJsonList>();}return JsonList;}/*** \enum JsonToken*/enum JsonToken {JsonTokenNone = 0,//JsonTokenCurlyOpen = 1,//{JsonTokenCurlyClose = 2,//}JsonTokenSquaredOpen = 3,//[JsonTokenSquaredClose = 4,//]JsonTokenColon = 5,//:JsonTokenComma = 6,//,JsonTokenString = 7//"};/*** parseValue*/static QVariant parseValue(const QString &json, int &index, bool &success) {switch(lookAhead(json, index)) {case JsonTokenString:return parseString(json, index, success);case JsonTokenCurlyOpen:return parseObject(json, index, success);case JsonTokenSquaredOpen:return parseArray(json, index, success);case JsonTokenNone:break;}success = false;return QVariant();}/*** parseObject解析 { 后的数据*/static QVariant parseObject(const QString &json, int &index, bool &success) {QVariantJsonList JsonList;int token;nextToken(json, index);bool done = false;while (!done) {token = lookAhead(json, index);if (token == JsonTokenNone) {success = false;return QVariant();} else if (token == JsonTokenComma) {nextToken(json, index);} else if (token == JsonTokenCurlyClose) {nextToken(json, index);return QVariant::fromValue(JsonList);} else {QString key = parseString(json, index, success).toString();if (!success) {return QVariant();}token = nextToken(json, index);if (token != JsonTokenColon) {success = false;return QVariant::fromValue(JsonList);}QVariant value = parseValue(json, index, success);if (!success) {return QVariant();}stJsonNodeData JsonNode = {key, value};JsonList.append(JsonNode);}}return QVariant::fromValue(JsonList);}/*** parseArray*/static QVariant parseArray(const QString &json, int &index, bool &success) {QVariantList list;nextToken(json, index);bool done = false;while(!done) {int token = lookAhead(json, index);if (token == JsonTokenNone) {success = false;return QVariantList();} else if (token == JsonTokenComma) {nextToken(json, index);} else if (token == JsonTokenSquaredClose) {nextToken(json, index);break;} else {QVariant value = parseValue(json, index, success);if (!success) {return QVariantList();}list.push_back(value);}}return QVariant(list);}/*** parseString*/static QVariant parseString(const QString &json, int &index, bool &success) {QString s;QChar c;eatWhitespace(json, index);c = json[index++];bool complete = false;while(!complete) {if (index == json.size()) {break;}c = json[index++];if (c == '\"') {complete = true;break;} else if (c == '\\') {if (index == json.size()) {break;}c = json[index++];if (c == '\"') {s.append('\"');} else if (c == '\\') {s.append('\\');} else if (c == '/') {s.append('/');} else if (c == 'b') {s.append('\b');} else if (c == 'f') {s.append('\f');} else if (c == 'n') {s.append('\n');} else if (c == 'r') {s.append('\r');} else if (c == 't') {s.append('\t');} else if (c == 'u') {int remainingLength = json.size() - index;if (remainingLength >= 4) {QString unicodeStr = json.mid(index, 4);int symbol = unicodeStr.toInt(0, 16);s.append(QChar(symbol));index += 4;} else {break;}}} else {s.append(c);}}if (!complete) {success = false;return QVariant();}return QVariant(s);}/*** eatWhitespace*/static void eatWhitespace(const QString &json, int &index) {for(; index < json.size(); index++) {if (QString(" \t\n\r").indexOf(json[index]) == -1) {break;}}}/*** lookAhead*/static int lookAhead(const QString &json, int index) {int saveIndex = index;return nextToken(json, saveIndex);}/*** nextToken*/static int nextToken(const QString &json, int &index) {eatWhitespace(json, index);if (index == json.size()) {return JsonTokenNone;}QChar c = json[index];index++;switch(c.toLatin1()) {case '{': return JsonTokenCurlyOpen;case '}': return JsonTokenCurlyClose;case '[': return JsonTokenSquaredOpen;case ']': return JsonTokenSquaredClose;case ',': return JsonTokenComma;case '"': return JsonTokenString;case ':': return JsonTokenColon;}index--;return JsonTokenNone;}} //end namespace
#ifndef JSON_H
#define JSON_H#include <QVariant>
#include <QString>
#include <QQueue>
#include <qjsonobject.h>struct stJsonNodeData
{QString m_key;QVariant m_value;
};typedef QList<stJsonNodeData> QVariantJsonList;Q_DECLARE_METATYPE(QVariantJsonList)//QVariant可以支持自定义的数据类型,使用Q_DECLARE_METATYPE()宏注册此类namespace QtJson {QVariantJsonList parse(const QString &json, bool &success);
}#endif //JSON_H

相关文章:

JSON与EXL文件互转

功能&#xff1a;实现json到excel文件的相互转换(支持json多选版) 目的&#xff1a;编码与语言对应&#xff0c;方便大家使用 页面设计&#xff1a; 介绍&#xff1a; 1.选择文件栏目选择想要转换的文件 2.生成路径是转换后文件所在目录 3.小方框勾选与不勾选分别代表exl到…...

后台管理权限自定义按钮指令v-hasPermi

第一步:在src下面建立一个自定义指令文件,放自定义指令方法 permission.js文件: /*** v-hasPermi 操作权限处理*/import store from "/store";export default {inserted(el, binding) {const { value } binding;//从仓库里面获取到后台给的数组const permission s…...

【Python绘制散点图并添加趋势线和公式以及相关系数和RMSE】

在Python中&#xff0c;绘制散点图并添加趋势线&#xff08;通常是线性回归线&#xff09;、公式、以及相关系数&#xff08;Pearson Correlation Coefficient&#xff09;和均方根误差&#xff08;RMSE&#xff09;可以通过结合matplotlib用于绘图&#xff0c;numpy用于数学运…...

linux bridge VLAN

TP-Link 支持 Linux 桥接&#xff08;bridge&#xff09;和 VLAN 功能的产品主要包括其高端的交换机和一些企业级路由器&#xff1a; TP-Link JetStream 系列交换机&#xff1a; TL-SG3424: 24端口千兆交换机&#xff0c;支持 VLAN 和桥接。TL-SG3210: 24端口千兆管理型交换机&…...

Java进阶篇之深入理解多态的概念与应用

引言 在Java面向对象编程&#xff08;OOP&#xff09;中&#xff0c;多态&#xff08;Polymorphism&#xff09;是一个关键概念&#xff0c;它允许相同类型的对象在不同的场景中表现出不同的行为。多态不仅增强了代码的灵活性和可扩展性&#xff0c;还极大地提高了代码的可维护…...

Linux下的进程调度队列

我们在进程那一篇讲到了操作系统时间片轮换调度的概念 那么Linux下具体是怎么调度的&#xff1f;...

统计回归与Matlab软件实现上(一元多元线性回归模型)

引言 关于数学建模的基本方法 机理驱动 由于客观事物内部规律的复杂及人们认识程度的限制&#xff0c;无法得到内在因果关系&#xff0c;建立合乎机理规律的数学模型数据驱动 直接从数据出发&#xff0c;找到隐含在数据背后的最佳模型&#xff0c;是数学模型建立的另一大思路…...

【项目】基于Vue3.2+ElementUI Plus+Vite 通用后台管理系统

构建项目 环境配置 全局安装vue脚手架 npm install -g vue/cli-init打开脚手架图形化界面 vue ui创建项目 在图形化界面创建项目根据要求填写项目相关信息选择手动配置勾选配置项目选择配置项目然后我们就搭建完成啦&#x1f973;&#xff0c;构建可能需要一点时间&#xff0…...

随机生成 UUID

1、随机生成 UUID主方法 /*** 随机生成 UUID* param {*} len 生成字符串的长度* param {*} radix 生成随机字符串的长度**/export function uuid_(len 30, radix 20) {var chars 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.split()var uuid [],ir…...

报名表EXCEL图片批量下载源码-CyberWinApp-SAAS 本地化及未来之窗行业应用跨平台架构

每次报名表都会包含大量照片&#xff0c;一张一张下载很慢 可以通过未来之窗开源平台架构 开开excel批量下载 实现代码也很简单 function 未来之窗下载(){ let 未来之窗地址 document.getElementById("batchurl").value; let 保存路径 document.getElementById(…...

SpringBoot 整合 Elasticsearch 实现商品搜索

一、Spring Data Elasticsearch Spring Data Elasticsearch 简介 Spring Data Elasticsearch是Spring提供的一种以Spring Data风格来操作数据存储的方式&#xff0c;它可以避免编写大量的样板代码。 常用注解 常用注解说明如下&#xff1a; 注解名称 作用 参数说明 Docu…...

计算机毕业设计 助农产品采购平台 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…...

Django后台数据获取展示

​ 续接Django REST Framework&#xff0c;使用Vite构建Vue3的前端项目 1.跨域获取后台接口并展示 安装Axios npm install axios --save 前端查看后端所有定义的接口 // 访问后端定义的可视化Api接口文档 http://ip:8000/docs/ // 定义的学生类信息 http://ip:8000/api/v1…...

innodb 如何保证数据的一致性?

InnoDB是MySQL的默认存储引擎之一&#xff0c;它通过多种机制来保证数据的一致性。以下是InnoDB保证数据一致性的主要方式&#xff1a; 1. 事务支持 InnoDB实现了ACID&#xff08;原子性、一致性、隔离性和持久性&#xff09;事务模型&#xff0c;这是保证数据一致性的基础。…...

Oracle-OracleConnection

提示&#xff1a;OracleConnection 主要负责与Oracle数据库的交互&#xff0c;特别针对CDC功能&#xff0c;提供了获取和处理数据库更改日志的能力&#xff0c;同时包含数据库连接管理、查询执行和结果处理的通用功能&#xff0c;与DB2Connection作用相似 文章目录 前言一、核心…...

基于hadoop的网络流量分析系统的研究与应用

目录 摘要 1 Abstract 2 第1章 绪论 3 1.1 研究背景 3 1.2 研究目的和意义 4 1.2.1 研究目的 4 1.2.2 研究意义 6 1.3 国内外研究现状分析 7 1.3.1 国内研究现状 7 1.3.2 国外研究现状 9 1.4 研究内容 11 第2章 Hadoop技术及相关组件介绍 12 2.1 HDFS的工作原理及…...

【C# WPF WeChat UI 简单布局】

创建WPF项目 VS创建一个C#的WPF应用程序: 创建完成后项目目录下会有一个MainWindow.xaml文件以及MainWindow.cs文件,此处将MainWindow.xaml文件作为主页面的布局文件,也即为页面的主题布局都在该文件进行。 布局和数据 主体布局 Wechat的布局可暂时分为三列, 第一列为菜…...

关于docker的几个概念(二)

目录 1. 为何Docker CentOS镜像比传统CentOS镜像小得多&#xff1f;2. 镜像的分层结构及其优势3. 讲一下容器的copy-on-write特性&#xff0c;修改容器里面的内容会修改镜像吗&#xff1f;4. 简单描述一下Dockerfile的整个构建镜像过程 1. 为何Docker CentOS镜像比传统CentOS镜…...

JAVA集中学习第五周学习记录(一)

系列文章目录 第一章 JAVA集中学习第一周学习记录(一) 第二章 JAVA集中学习第一周项目实践 第三章 JAVA集中学习第一周学习记录(二) 第四章 JAVA集中学习第一周课后习题 第五章 JAVA集中学习第二周学习记录(一) 第六章 JAVA集中学习第二周项目实践 第七章 JAVA集中学习第二周学…...

JavaSE 网络编程

什么是网络编程 计算机与计算机之间通过网络进行数据传输 两种软件架构 网络编程3要素 IP IPv4 IPv6 Testpublic void test01() throws UnknownHostException { // InetAddress.getByName 可以是名字或ipInetAddress address InetAddress.getByName("LAPTOP-7I…...

ubuntu24.04 编译安装PHP7.4

ubuntu24.04 编译安装PHP7.4 先安装依赖包&#xff08;原本是centos上安装依赖&#xff0c;让chatgpt转换了下对应的ubutnu下包名&#xff0c;如果编译过程有缺失&#xff0c;按报错提示再安装下&#xff09; apt install zlib1g zlib1g-dev libpcre3 libpcre3-dev libfreety…...

Tied and Anchored Stereo Attention Network for Cloud Removal in Optical

论文名称 基于固定锚定立体注意力网络的光学遥感图像去云方法代码运行 论文代码 https://github.com/ningjin00/TASANet?tabreadme-ov-file 论文地址 1环境创建 模型环境给了这几个包&#xff0c;如果你自带环境 那就运行代码 提示缺哪个装哪个 python 3.12rasterio 1.3.10…...

云开发微信小程序--即时聊天(单人聊天,多人聊天室)

云开发微信小程序–即时聊天 介绍&#xff1a;本小程序包含欢迎界面&#xff0c;注册&#xff0c;登录&#xff0c;一对一聊天&#xff0c;群聊&#xff0c;好友添加请求验证过程&#xff0c;修改好友备注以及删除好友&#xff0c;退出群聊&#xff0c;特殊角色卡片展示&#…...

Leetcod编程基础0到1-基础实现内容(个人解法)(笔记)

以下为个人解法&#xff0c;欢迎提供不同思路 1768. 交替合并字符串 题目&#xff1a;给你两个字符串 word1 和 word2 。请你从 word1 开始&#xff0c;通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长&#xff0c;就将多出来的字母追加到合并后字符串的末尾&…...

仲阳天王星运维实习一面

自我介绍&#xff1f; 略谈谈你对“仲阳天王星”的理解&#xff1f; 略实习时间怎么安排&#xff0c;后续时间是怎么规划的&#xff1f; 略给你一个装满水的8升满壶和两个分别是5升、3升的空壶&#xff0c;请想个办法&#xff0c;使得其中一个水壶恰好装4升水&#xff0c;每一步…...

排序算法详解

​ &#x1f48e;所属专栏&#xff1a;数据结构与算法学习 &#x1f48e; 欢迎大家互三&#xff1a;2的n次方_ &#x1f341;1. 插入排序 &#x1f341;1.1 直接插入排序 插入排序是一种简单直观的排序算法&#xff0c;它的原理是通过构建有序序列&#xff0c;对于未排序数…...

vxe-table树形结构使用setCheckboxRow卡顿--已解决

项目场景&#xff1a; vxe-table树形结构使用setCheckboxRow进行部分节点选中 问题描述 vxe-table树形结构使用setCheckboxRow&#xff0c;在数据较多时卡顿 原因分析&#xff1a; setCheckboxRow内部进行了多次的循环遍历&#xff0c;导致速度慢 解决方案&#xff1a; 设…...

配置错误和 IAM 弱点是云安全的主要隐患

根据云安全联盟发布的《2024 年云计算最大威胁》报告&#xff0c;通常与云服务提供商 (CSP) 相关的传统云安全问题的重要性正在持续下降。 配置错误、IAM 弱点和 API 风险仍然至关重要 这些发现延续了 2022 年报告中首次发现的轨迹&#xff0c;同时&#xff0c;诸如错误配置的…...

Redis系列之Redis Cluster

概述 Redis 2.8版本发布稳定版Redis Sentinel&#xff0c;不过Sentinel集群版存在一些问题&#xff1a; 高可用性&#xff1a;Sentinel集群对Redis既有的主从集群提供有限的高可用保障&#xff1b;在线扩容&#xff1a;节点下线&#xff0c;触发选举&#xff0c;选举涉及两个…...

网站证书过期导致WordPress后台无法登录问题解决,页面样式丢失

1、首先打开网站目录文件\wp-includes\functions.php&#xff0c;找到代码&#xff0c;应该就是就在在第8行。 require( ABSPATH . WPINC . /option.php ); 在下面添加以下代码&#xff0c;作用就是把http替换为https add_filter(script_loader_src, agnostic_script_loader…...