JSON与EXL文件互转

news2024/11/14 7:37:20

功能:实现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_OBJECT

public:
    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转EXL
            if(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转JSON
            bool 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);//将数据转为QString
        bool 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,文件命名为源文件名字,多转一命名为JsonToExl
    if(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()");//关闭excel
    delete 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;
            else
                NodeData.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";
        else
            jsonString += "\"" + 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);
            else
                NodeString += jsonDatatoString(NodeData, level + 1, false);
        }
        NodeString.chop(1);
        if(last)
            jsonString += "{\n" + NodeString + indentation + "}\n\n";
        else
            jsonString += "{\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_OBJECT

public:
    ConvertThread();
    ~ConvertThread();    
public slots:
    void setConvert(eConvertType ConvertType, const QStringList SelectFile, const QString GeneratePath);

private:
    bool analysisJson(QString FileName, int FileOrder);//解析json
    QList<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);//解析excel
    void 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2041682.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Apache Doris 中Compaction问题分析和典型案例

说明 此文档主要说明一些常见compaction问题的排查思路和临时处理手段。这些问题包括 Compaction socre高Compaction失败compaction占用资源多Compaction core 如果问题紧急&#xff0c;可联系社区同学处理 如果阅读中有问题&#xff0c;可以反馈给社区同学。 1 compaction …

VulnHub:BlueMoon

准备工作 靶机下载地址&#xff0c;下载完成后使用virtualbox打开虚拟机&#xff0c;网络设置修改为桥接。 信息收集 主机发现 攻击机ip&#xff1a;192.168.31.218&#xff0c;nmap扫描攻击机同网段存活主机。 nmap 192.168.31.0/24 -Pn -T4 目标靶机ip为&#xff1a;192…

Docker最佳实践进阶(一):Dockerfile介绍使用

大家好&#xff0c;上一个系列我们使用docker安装了一系列的基础服务&#xff0c;但在实际开发过程中这样一个个的安装以及繁杂命令不仅仅浪费时间&#xff0c;更是容易遗忘&#xff0c;下面我们进行Docker的进阶教程&#xff0c;帮助我们更快速的部署和演示项目。 一、什么是…

免费抠图项目

零元部署一个产品落地页 最近花了点时间&#xff0c;为我之前写的AI抠图项目&#xff0c;写了个产品落地页&#xff0c;效果如下。 项目使用tailwindcss和vue3实现&#xff0c;支持主题切换、中英文切换等功能。 更多功能可以点击Matting Website查看。 部署这个页面几乎是0元…

Linux文件系统之RAID

文章目录 1、前言2、RAID特性简述3、RAID实现方式4、RAID级别①RAID-0②RAID-1③RAID-5④RAID-6⑤RAID-10和RAID-01 1、前言 RAID全称Redundant Arrays of Inexpensive Disks / Redundant Arrays of Independent Disks&#xff0c;即独立冗余磁盘阵列。RAID可以通过相关技术&a…

纷享销客CRM AI产品架构概览、产品特色

一、纷享销客CRM AI产品架构概览 纷享AI平台架构分为三个主要层次&#xff1a;AI基础设施层、AI平台层和AI应用层。每个层次都由一系列功能模块组成&#xff0c;旨在为客户提供强大的技术支持和灵活的解决方案。 1.Al基础设施层 AI基础设施层是整个AI平台的底层支撑&#xff…

Spark MLlib 特征工程(上)

文章目录 Spark MLlib 特征工程(上)特征工程预处理 Encoding:StringIndexer特征构建:VectorAssembler特征选择:ChiSqSelector归一化:MinMaxScaler模型训练总结Spark MLlib 特征工程(上) 前面我们一起构建了一个简单的线性回归模型,来预测美国爱荷华州的房价。从模型效果来…

【高等代数笔记】002.高等代数研究对象(二)

1. 高等代数的研究对象 1.4 一元高次方程的求根 a n x n a n − 1 x n − 1 . . . a 1 x a 0 0 a_{n}x^{n}a_{n-1}x^{n-1}...a_{1}xa_{0}0 an​xnan−1​xn−1...a1​xa0​0 等式左边是一元多项式。 所有一元多项式组成的集合称为一元多项式环。

在亚马逊云科技上安全、合规地创建AI大模型训练基础设施并开发AI应用服务

项目简介&#xff1a; 小李哥将继续每天介绍一个基于亚马逊云科技AWS云计算平台的全球前沿AI技术解决方案&#xff0c;帮助大家快速了解国际上最热门的云计算平台亚马逊云科技AWS AI最佳实践&#xff0c;并应用到自己的日常工作里。 本次介绍的是如何在亚马逊云科技利用Servi…

ARM架构(四)——异常中断和中断控制器(GIC)①

中断术语1——assert、routing、target、target to、target fromtaken 几个重要的概念:assert。routing、target、target to、target fromtaken 1.2 assert 外设发给GIC一个中断信号&#xff0c;GIC发给PE&#xff0c;PE对中断进行assert&#xff0c;断言这个中断是IRQ还是FI…

PPT怎么锁定图片不被移动?2个办公必备的实用技巧盘点!

插入到ppt的图片&#xff0c;怎么锁定不被移动&#xff1f;这是不少做PPT的人都会遇到的问题&#xff0c;想要移动的图片不会移动&#xff0c;不想移动的图片反而动了……诸如此类的迷之操作&#xff0c;直接把人整迷糊了。 ppt怎么锁定图片不被移动&#xff1f;就着这个问题&…

(贪心 + 双指针) LeetCode 455. 分发饼干

原题链接 一. 题目描述 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b;并且每块饼干 j&…

【数学建模备赛】Ep03:皮尔逊person相关系数

文章目录 一、前言&#x1f680;&#x1f680;&#x1f680;二、皮尔逊person相关系数&#xff1a;☀️☀️☀️1. 总体皮尔逊person相关系数① 总体和样本② 理解协方差&#xff08;受量纲影响&#xff09;③ 剔除量纲影响 2. 样本皮尔逊person相关系数3. 相关性可视化① 皮尔…

后端代码练习1——加法计算器

1. 需求 输入两个整数&#xff0c;点击 “点击相加” 按钮&#xff0c;显示计算结果。 2.准备工作 创建Spring Boot项目&#xff0c;引入Spring Web依赖&#xff0c;把前端代码放入static目录下。 2.1 前端代码 <!DOCTYPE html> <html lang"en"> <h…

Unity + HybridCLR 从零开始

官方文档开始学习,快速上手 | HybridCLR (code-philosophy.com)是官方文档链接 1.建议使用2019.4.40、2020.3.26、 2021.3.0、2022.3.0 中任一版本至于其他2019-2022LTS版本可能出现打包失败情况 2. Windows Win下需要安装visual studio 2019或更高版本。安装时至少要包含 使…

apache-lotdb集群部署

一、下载 发行版本 | IoTDB Website jdk版本&#xff1a; 系统版本&#xff1a; 二、服务器规划 节点名称主机名服务192.168.110.110master01.110110.cnConfigNode、DataNode192.168.110.111node01.110111.cnConfigNode、DataNode192.168.110.112node02.110112.cnConfigNode、…

一文搞懂Python自动化测试框架!

一文搞懂Python自动化测试框架 如果你选用python做自动化测试&#xff0c;那么python测试框架的相关知识你必须要了解下。 首先我们先学习一下框架的基本知识。 什么是框架&#xff08;百度百科&#xff09;&#xff1f; 框架( Framwork )是构成一类特定软件可复用设计的一组…

100V-50mA超高压低压差线性稳压器具有电流保护功能

产品概述 PC6001 是一款能够耐受超高电压的线性稳压器&#xff0c;不仅融合了耐热增强型封装的优势&#xff0c;还能够承受持续直流电压或最高达 100V 的瞬态输入电压。 PC6001 器件与任何高于 2.2F 的输出电容以及高于0.47F 的输入电容搭配使用时均可保持稳定&#xff08;过…

mfc140u.dll丢失错误解决方法的基本思路——四种修复mfc140u.dll的方法

当遇到mfc140u.dll丢失的错误时&#xff0c;意味着你的系统中缺失了一个重要的动态链接库文件&#xff0c;该文件是微软 Visual C Redistributable for Visual Studio 2015 的一部分&#xff0c;对于运行那些用 Visual C 开发的程序是必需的。今天就教你mfc140u.dll丢失错误解决…

派单系统功能案例分析

派单系统是一种专门用于协调和分配任务的软件系统&#xff0c;它通过自动化和智能化的方式&#xff0c;确保任务能够高效地完成。以下是对派单系统功能的案例分析&#xff0c;主要从任务分配、实时监控、数据统计与分析以及行业应用等方面进行阐述。 一、任务分配 派单系统的核…