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

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值