【MFC】数据库操作:数据库动态生成

实现功能:

程序中struct数据结构转化为json文件保存

  • 1.将程序中的struct数据集合保存成json格式。每次测试需要进行保存的数据可以生成一个新的json文件,用来传输。

例如:

c 复制代码
//定义需要
typedef struct _PModelJsonTest3
{
    std::string Test3Num1;
    int Test3Num2;
    double Test3Num3;

    NLOHMANN_DEFINE_TYPE_INTRUSIVE(_PModelJsonTest3, Test3Num1, Test3Num2, Test3Num3)
}PModelJsonTest3;

在程序中调用

c 复制代码
//测试将数据类转化为json文件
CDataClassToJson converter;

///测试将数据类转化为json文件
CDataClassToJson converter;/ 示例2: 使用PModel数据类
PModelJsonTest3 P2model3;
P2model3.Test3Num1 = "string";
P2model3.Test3Num2 = 222222;
P2model3.Test3Num3 = 333333;

if (converter.ConvertToJsonFile(P2model3, CreateCodeFileName, _T("Pro2"), _T("PModelJsonTest3"))) {
	AfxMessageBox(_T("PModelJsonTest3转换成功!"));
}
else
{
	AfxMessageBox(_T("PModelJsonTest3转换失败!"));
}

生成的json文件格式:

c 复制代码
{
    "Pro2": {
        "PModelJsonTest3": {
            "Test3Num1": "string",
            "Test3Num2": 222222,
            "Test3Num3": 333333.0
        }
    }
}

DB数据库的操作

  • 1.初始化传入一个作为模板的json文件,会根据这个模板json文件的格式生成对应的数据库表【如果监测到数据库存在,或直接打开,之前的记录不会覆盖】
    例如:类似生成Pro2,添加Pro1和Pro3,会生成一下DB数据结构:


调用:

c 复制代码
UpdateData();

//这个需要定义在对话框类中
CDynamicJsonSQLiteDB db;

if (db.InitializeDBFromJson(_T(filePathDir+ uiData_DBInitJsonFileName))) {
	AfxMessageBox(_T("数据库初始化成功!数据库路径: ") + db.GetDBPath());

	CString strInfo;
	strInfo.Format(_T("当前记录数量: %d"), db.GetRecordCount());
	AfxMessageBox(strInfo);
}
else {
	AfxMessageBox(_T("初始化失败: ") + db.GetLastError());
	return;
}
  • 2.添加接口,传入一组数据json文件会在数据库中添加新的一组数据【此文件结构需要跟初始化json的结构相同,否则会报错】
c 复制代码
UpdateData();

// 2. 添加数据记录(传入JSON文件名)
if (db.AddDataRecord(_T(filePathDir + uiData_DBAddJsonFileName))) {
	AfxMessageBox(_T("数据记录1添加成功!"));
}
else {
	AfxMessageBox(_T("数据记录添加失败: ") + db.GetLastError());
}

// 显示当前记录数量
CString strCount;
strCount.Format(_T("当前总记录数: %d"), db.GetRecordCount());
AfxMessageBox(strCount);
  • 3.传入需要导出的序列号,导出数据库中的改数据,为一个json文件
c 复制代码
UpdateData();
CString filePathDir = "D:\\DB\\DBJson_Test\\";

if (db.ExportDataToJson(uiData_DBOutDBNum, _T(filePathDir + "DB_OutJson.json"))) {

	CString strCount;
	strCount.Format(_T("第 %d 条记录导出成功!"), uiData_DBOutDBNum);
	AfxMessageBox(strCount);

}
else {
	CString strCount;
	strCount.Format(_T("第%d条记录导出失败: !"), uiData_DBOutDBNum);
	AfxMessageBox(strCount + db.GetLastError());
}
  • 4.操作完成后关闭数据库
c 复制代码
db.CloseDB();

以下为程序中的数据结构转json实现接口:

注意需要导入使用 nlohmann/json 库,可以从官网下载json.hpp,直接放入程序中引用即可

CDataClassToJson.h

cpp 复制代码
#pragma once

#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <type_traits>
#include <fstream>
#include <sstream>
#include "json.hpp"  // 使用 nlohmann/json 库

using json = nlohmann::json;


#ifdef UNICODE
#include <windows.h>
#endif

// 反射辅助宏
#define DEFINE_FIELD(Class, Field) \
    std::make_pair(#Field, [](const Class& obj) -> std::string { \
        if constexpr (std::is_arithmetic_v<decltype(obj.Field)>) { \
            return std::to_string(obj.Field); \
        } else if constexpr (std::is_same_v<decltype(obj.Field), std::string>) { \
            return "\"" + obj.Field + "\""; \
        } else if constexpr (std::is_same_v<decltype(obj.Field), const char*>) { \
            return "\"" + std::string(obj.Field) + "\""; \
        } else { \
            return "\"" + std::to_string(obj.Field) + "\""; \
        } \
    })

// 通用的JSON文件管理器
class CDataClassToJson
{
public:
    CDataClassToJson();
    virtual ~CDataClassToJson();

    // 辅助函数
    CString GetLastError() const { return m_strLastError; }
    BOOL FileExists(LPCTSTR lpszFilePath);
    CString ReadFileToString(LPCTSTR lpszFilePath);
    BOOL WriteStringToFile(LPCTSTR lpszFilePath, LPCTSTR lpszContent);

private:
    CString m_strLastError;

    // 内部方法
    BOOL EnsureJsonFileExists(LPCTSTR lpszJsonFilePath, LPCTSTR lpszProgramName);
    BOOL UpdateJsonFileWithData(LPCTSTR lpszJsonFilePath,
        LPCTSTR lpszProgramName,
        LPCTSTR lpszClassName,
        const std::map<std::string, std::string>& fieldValues);

    // 字符串转换
    std::string CStringToStdString(LPCTSTR lpszStr);
    CString StdStringToCString(const std::string& str);


public:
    //// 主要接口:将数据类转换为JSON文件
    //在C++中,模板函数的定义必须在使用时可见
    // 序列化到JSON文件 - 支持同一程序下多类名数据合并,不覆盖同类名数据
    template<typename T>
    static BOOL ConvertToJsonFile(const T& dataObj,
        LPCTSTR lpszJsonFilePath,
        LPCTSTR lpszProgramName,
        LPCTSTR lpszClassName = nullptr) {

        try {
            json root;

            // 如果文件已存在,先读取现有数据
            std::ifstream ifs(TCHARToString(lpszJsonFilePath));
            if (ifs.is_open()) {
                ifs >> root;
                ifs.close();
            }

            std::string programName = TCHARToString(lpszProgramName);
            std::string className = TCHARToString(lpszClassName);

            // 如果程序节点不存在,创建它
            if (!root.contains(programName)) {
                root[programName] = json::object();
            }

            // 如果类名节点不存在,创建它
            if (!root[programName].contains(className)) {
                root[programName][className] = json::object();
            }

            // 合并数据:将新数据合并到现有类数据中
            MergeJsonData(root[programName][className], dataObj);

            // 写回文件
            std::ofstream ofs(TCHARToString(lpszJsonFilePath));
            if (!ofs.is_open()) {
                return FALSE;
            }

            ofs << root.dump(4);
            return TRUE;
        }
        catch (const std::exception& e) {
            std::cerr << "ConvertToJsonFile error: " << e.what() << std::endl;
            return FALSE;
        }
        catch (...) {
            std::cerr << "ConvertToJsonFile unknown error" << std::endl;
            return FALSE;
        }
    }


    //// 从JSON文件读取到数据类
    // 从JSON文件反序列化指定类的数据
    template<typename T>
    static BOOL ConvertFromJsonFile(T& dataObj,
        LPCTSTR lpszJsonFilePath,
        LPCTSTR lpszProgramName,
        LPCTSTR lpszClassName = nullptr) {

        try {
            std::ifstream ifs(TCHARToString(lpszJsonFilePath));
            if (!ifs.is_open()) {
                return FALSE;
            }

            json root;
            ifs >> root;

            std::string programName = TCHARToString(lpszProgramName);
            std::string className = TCHARToString(lpszClassName);

            if (!root.contains(programName)) {
                return FALSE;
            }

            if (!root[programName].contains(className)) {
                return FALSE;
            }

            // 只反序列化指定类的数据
            dataObj = root[programName][className].get<T>();
            return TRUE;
        }
        catch (const std::exception& e) {
            std::cerr << "ConvertFromJsonFile error: " << e.what() << std::endl;
            return FALSE;
        }
        catch (...) {
            std::cerr << "ConvertFromJsonFile unknown error" << std::endl;
            return FALSE;
        }
    }

    // 从JSON文件反序列化整个程序的所有类数据
    template<typename T>
    static BOOL ConvertAllClassesFromJsonFile(std::map<std::string, T>& classDataMap,
        LPCTSTR lpszJsonFilePath,
        LPCTSTR lpszProgramName) {

        try {
            std::ifstream ifs(TCHARToString(lpszJsonFilePath));
            if (!ifs.is_open()) {
                return FALSE;
            }

            json root;
            ifs >> root;

            std::string programName = TCHARToString(lpszProgramName);

            if (!root.contains(programName)) {
                return FALSE;
            }

            classDataMap.clear();
            for (auto it = root[programName].begin(); it != root[programName].end(); ++it) {
                T data;
                data = it.value().get<T>();
                classDataMap[it.key()] = data;
            }

            return TRUE;
        }
        catch (const std::exception& e) {
            std::cerr << "ConvertAllClassesFromJsonFile error: " << e.what() << std::endl;
            return FALSE;
        }
        catch (...) {
            std::cerr << "ConvertAllClassesFromJsonFile unknown error" << std::endl;
            return FALSE;
        }
    }

    // 序列化到字符串 - 支持合并
    template<typename T>
    static std::string ConvertToJsonString(const T& dataObj,
        const std::string& existingJsonStr,
        LPCTSTR lpszProgramName,
        LPCTSTR lpszClassName = nullptr) {

        try {
            json root;

            if (!existingJsonStr.empty()) {
                root = json::parse(existingJsonStr);
            }

            std::string programName = TCHARToString(lpszProgramName);
            std::string className = TCHARToString(lpszClassName);

            if (!root.contains(programName)) {
                root[programName] = json::object();
            }

            if (!root[programName].contains(className)) {
                root[programName][className] = json::object();
            }

            MergeJsonData(root[programName][className], dataObj);

            return root.dump(4);
        }
        catch (const std::exception& e) {
            std::cerr << "ConvertToJsonString error: " << e.what() << std::endl;
            return "";
        }
    }

    // 新增:获取整个JSON文件内容
    static std::string ReadJsonFile(LPCTSTR lpszJsonFilePath) {
        try {
            std::ifstream ifs(TCHARToString(lpszJsonFilePath));
            if (!ifs.is_open()) {
                return "{}";
            }

            std::string content((std::istreambuf_iterator<char>(ifs)),
                std::istreambuf_iterator<char>());
            return content;
        }
        catch (...) {
            return "{}";
        }
    }

    // 新增:获取文件中的所有程序名
    static std::vector<std::string> GetProgramNames(LPCTSTR lpszJsonFilePath) {
        std::vector<std::string> programs;
        try {
            std::ifstream ifs(TCHARToString(lpszJsonFilePath));
            if (!ifs.is_open()) {
                return programs;
            }

            json root;
            ifs >> root;

            for (auto it = root.begin(); it != root.end(); ++it) {
                programs.push_back(it.key());
            }
        }
        catch (...) {
            // 忽略错误,返回空列表
        }
        return programs;
    }

    // 新增:获取指定程序中的所有类名
    static std::vector<std::string> GetClassNames(LPCTSTR lpszJsonFilePath, LPCTSTR lpszProgramName) {
        std::vector<std::string> classes;
        try {
            std::ifstream ifs(TCHARToString(lpszJsonFilePath));
            if (!ifs.is_open()) {
                return classes;
            }

            json root;
            ifs >> root;

            std::string programName = TCHARToString(lpszProgramName);
            if (root.contains(programName)) {
                for (auto it = root[programName].begin(); it != root[programName].end(); ++it) {
                    classes.push_back(it.key());
                }
            }
        }
        catch (...) {
            // 忽略错误,返回空列表
        }
        return classes;
    }

    // 新增:删除指定的程序数据
    static BOOL RemoveProgram(LPCTSTR lpszJsonFilePath, LPCTSTR lpszProgramName) {
        try {
            json root;

            std::ifstream ifs(TCHARToString(lpszJsonFilePath));
            if (ifs.is_open()) {
                ifs >> root;
                ifs.close();
            }

            std::string programName = TCHARToString(lpszProgramName);

            if (root.contains(programName)) {
                root.erase(programName);

                std::ofstream ofs(TCHARToString(lpszJsonFilePath));
                if (!ofs.is_open()) {
                    return FALSE;
                }

                ofs << root.dump(4);
                return TRUE;
            }

            return FALSE;
        }
        catch (...) {
            return FALSE;
        }
    }

    // 新增:删除指定的类数据
    static BOOL RemoveClass(LPCTSTR lpszJsonFilePath, LPCTSTR lpszProgramName, LPCTSTR lpszClassName) {
        try {
            json root;

            std::ifstream ifs(TCHARToString(lpszJsonFilePath));
            if (ifs.is_open()) {
                ifs >> root;
                ifs.close();
            }

            std::string programName = TCHARToString(lpszProgramName);
            std::string className = TCHARToString(lpszClassName);

            if (root.contains(programName) && root[programName].contains(className)) {
                root[programName].erase(className);

                if (root[programName].empty()) {
                    root.erase(programName);
                }

                std::ofstream ofs(TCHARToString(lpszJsonFilePath));
                if (!ofs.is_open()) {
                    return FALSE;
                }

                ofs << root.dump(4);
                return TRUE;
            }

            return FALSE;
        }
        catch (...) {
            return FALSE;
        }
    }

    // 新增:检查指定的类是否存在
    static BOOL ClassExists(LPCTSTR lpszJsonFilePath, LPCTSTR lpszProgramName, LPCTSTR lpszClassName) {
        try {
            std::ifstream ifs(TCHARToString(lpszJsonFilePath));
            if (!ifs.is_open()) {
                return FALSE;
            }

            json root;
            ifs >> root;

            std::string programName = TCHARToString(lpszProgramName);
            std::string className = TCHARToString(lpszClassName);

            return root.contains(programName) && root[programName].contains(className);
        }
        catch (...) {
            return FALSE;
        }
    }

private:
    // TCHAR 到 string 的转换
    static std::string TCHARToString(LPCTSTR str) {
        if (str == nullptr) return "";
#ifdef UNICODE
        int len = WideCharToMultiByte(CP_UTF8, 0, str, -1, nullptr, 0, nullptr, nullptr);
        if (len == 0) return "";
        std::string result(len - 1, 0);
        WideCharToMultiByte(CP_UTF8, 0, str, -1, &result[0], len, nullptr, nullptr);
        return result;
#else
        return std::string(str);
#endif
    }

    // 合并JSON数据的辅助函数
    template<typename T>
    static void MergeJsonData(json& target, const T& source) {
        // 将源对象转换为JSON
        json sourceJson = source;

        // 如果目标是空对象,直接赋值
        if (target.empty() || !target.is_object()) {
            target = sourceJson;
            return;
        }

        // 合并对象:对于相同的字段,使用源数据覆盖;对于不同的字段,保留两者
        if (sourceJson.is_object() && target.is_object()) {
            for (auto it = sourceJson.begin(); it != sourceJson.end(); ++it) {
                target[it.key()] = it.value();
            }
        }
        else {
            // 如果不是对象,直接覆盖
            target = sourceJson;
        }
    }
};

CDataClassToJson.cpp

c 复制代码
#include "stdafx.h"
#include "DataClassToJson.h"

#include <fstream>
#include <sstream>

CDataClassToJson::CDataClassToJson()
{
}

CDataClassToJson::~CDataClassToJson()
{
}

BOOL CDataClassToJson::FileExists(LPCTSTR lpszFilePath)
{
    CFileStatus status;
    return CFile::GetStatus(lpszFilePath, status);
}

CString CDataClassToJson::ReadFileToString(LPCTSTR lpszFilePath)
{
    CString strContent;
    CStdioFile file;

    if (file.Open(lpszFilePath, CFile::modeRead | CFile::typeText)) {
        CString strLine;
        while (file.ReadString(strLine)) {
            strContent += strLine;
        }
        file.Close();
    }
    else {
        m_strLastError.Format(_T("无法打开文件: %s"), lpszFilePath);
    }

    return strContent;
}

BOOL CDataClassToJson::WriteStringToFile(LPCTSTR lpszFilePath, LPCTSTR lpszContent)
{
    CStdioFile file;

    if (file.Open(lpszFilePath, CFile::modeCreate | CFile::modeWrite | CFile::typeText)) {
        file.WriteString(lpszContent);
        file.Close();
        return TRUE;
    }

    m_strLastError.Format(_T("无法写入文件: %s"), lpszFilePath);
    return FALSE;
}

std::string CDataClassToJson::CStringToStdString(LPCTSTR lpszStr)
{
#ifdef _UNICODE
    // Unicode 转 ANSI
    int nLen = WideCharToMultiByte(CP_UTF8, 0, lpszStr, -1, NULL, 0, NULL, NULL);
    if (nLen <= 0) return "";

    char* pBuffer = new char[nLen];
    WideCharToMultiByte(CP_UTF8, 0, lpszStr, -1, pBuffer, nLen, NULL, NULL);
    std::string result(pBuffer);
    delete[] pBuffer;
    return result;
#else
    // ANSI 直接转换
    return std::string(lpszStr);
#endif
}

CString CDataClassToJson::StdStringToCString(const std::string& str)
{
#ifdef _UNICODE
    // ANSI 转 Unicode
    int nLen = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
    if (nLen <= 0) return _T("");

    wchar_t* pBuffer = new wchar_t[nLen];
    MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, pBuffer, nLen);
    CString result(pBuffer);
    delete[] pBuffer;
    return result;
#else
    // ANSI 直接转换
    return CString(str.c_str());
#endif
}

BOOL CDataClassToJson::EnsureJsonFileExists(LPCTSTR lpszJsonFilePath, LPCTSTR lpszProgramName)
{
    if (FileExists(lpszJsonFilePath)) {
        return TRUE;  // 文件已存在
    }

    // 创建新的JSON文件结构
    std::string strProgramName = CStringToStdString(lpszProgramName);

    json newJson;
    newJson[strProgramName] = json::object();  // 创建空的Program对象

    // 写入文件
    std::ofstream file(CStringToStdString(lpszJsonFilePath));
    if (!file.is_open()) {
        m_strLastError.Format(_T("无法创建JSON文件: %s"), lpszJsonFilePath);
        return FALSE;
    }

    file << newJson.dump(4);  // 缩进4个空格
    file.close();

    return TRUE;
}

BOOL CDataClassToJson::UpdateJsonFileWithData(LPCTSTR lpszJsonFilePath,
    LPCTSTR lpszProgramName,
    LPCTSTR lpszClassName,
    const std::map<std::string, std::string>& fieldValues)
{
    try {
        // 读取现有JSON文件
        std::ifstream file(CStringToStdString(lpszJsonFilePath));
        if (!file.is_open()) {
            m_strLastError.Format(_T("无法打开JSON文件: %s"), lpszJsonFilePath);
            return FALSE;
        }

        json jsonData;
        file >> jsonData;
        file.close();

        std::string strProgramName = CStringToStdString(lpszProgramName);
        std::string strClassName = lpszClassName ? CStringToStdString(lpszClassName) : "DataClass";

        // 确保Program存在
        if (!jsonData.contains(strProgramName)) {
            jsonData[strProgramName] = json::object();
        }

        // 确保Class存在
        if (!jsonData[strProgramName].contains(strClassName)) {
            jsonData[strProgramName][strClassName] = json::object();
        }

        // 更新字段值
        for (const auto& field : fieldValues) {
            jsonData[strProgramName][strClassName][field.first] = field.second;
        }

        // 写回文件
        std::ofstream outFile(CStringToStdString(lpszJsonFilePath));
        if (!outFile.is_open()) {
            m_strLastError.Format(_T("无法写入JSON文件: %s"), lpszJsonFilePath);
            return FALSE;
        }

        outFile << jsonData.dump(4);
        outFile.close();

        return TRUE;
    }
    catch (const std::exception& e) {
        m_strLastError = _T("JSON处理错误: ") + CString(e.what());
        return FALSE;
    }
}

以下为DB数据库新建和添加json文件的接口:

注意需要导入sqlite3数据库

sqlite3详细安装和导入方式可见:点击进入sqlite3数据库安装配置

CDynamicJsonSQLiteDB.h

cpp 复制代码
#pragma once
#pragma once

#include <vector>
#include <map>
#include <string>
#include "sqlite3.h"

class CDynamicJsonSQLiteDB
{
public:
    CDynamicJsonSQLiteDB();
    virtual ~CDynamicJsonSQLiteDB();


    // 主要接口
    BOOL InitializeDBFromJson(LPCTSTR lpszJsonFilePath);
    BOOL AddDataRecord(LPCTSTR lpszJsonFilePath);  // 修改:传入JSON文件名
    BOOL ExportDataToJson(int nRecordNum, LPCTSTR lpszOutputJsonFile);

    // 辅助函数
    BOOL IsDBOpen() const { return m_pDB != NULL; }
    CString GetLastError() const { return m_strLastError; }
    void CloseDB();
    CString GetDBPath() const { return m_strDBPath; }

    // 新增:获取当前记录数量
    int GetRecordCount();

private:
    BOOL ValidateFilePath(LPCTSTR lpszFilePath);
    CString GetValidFileName(LPCTSTR lpszFileName);

private:
    sqlite3* m_pDB;
    CString m_strDBPath;
    CString m_strLastError;

    // JSON结构信息
    std::vector<CString> m_tableNames;  // 主表名(PROGRAM1, PROGRAM2等)
    std::map<CString, std::vector<CString>> m_tableFields; // 表字段映射
    std::map<CString, std::map<CString, std::vector<CString>>> m_subTableFields; // 子表字段映射

    // 内部方法
    CString ReadJsonFile(LPCTSTR lpszFilePath);
    BOOL WriteJsonFile(LPCTSTR lpszFilePath, LPCTSTR lpszContent);
    BOOL ExecuteSQL(LPCTSTR lpszSQL);
    BOOL TableExists(LPCTSTR lpszTableName);

    // JSON结构分析
    BOOL AnalyzeJsonStructure(LPCTSTR lpszJsonData);
    BOOL ParseJsonObject(LPCTSTR lpszJsonData, CString strParentKey = _T(""));
    void AddFieldToTable(const CString& strParentKey, const CString& strFieldName);
    BOOL CreateDatabaseTables();

    BOOL ValidateJsonStructure(LPCTSTR lpszJsonData);

    // 数据操作
    BOOL InsertJsonData(LPCTSTR lpszJsonData, int nRecordNum);  // 内部使用,传入JSON数据
    BOOL InsertJsonFromFile(LPCTSTR lpszJsonFilePath, int nRecordNum);  // 新增:从文件插入
    BOOL ParseAndInsertData(LPCTSTR lpszJsonData, CString strParentPath, int nRecordNum);
    void ExtractAllFieldsFromJson(LPCTSTR lpszJsonData, std::map<CString, CString>& fieldValues);

    // 数据导出
    CString GenerateJsonFromData(int nRecordNum);
    BOOL BuildJsonForTable(CString& strJson, LPCTSTR lpszTableName, int nRecordNum);

    // 字符串处理
    CString EscapeSQLString(LPCTSTR lpszInput);
    CString GetCurrentTimestamp();
    /*void CheckSQLiteTime();*/
    CString ExtractJsonValue(LPCTSTR lpszJsonData, LPCTSTR lpszKey);

    // 记录管理
    int GetNextRecordNum();

    // SQLite回调
    static int SQLiteCallback(void* data, int argc, char** argv, char** azColName);
};

struct SQueryResult
{
    std::vector<std::map<CString, CString>> rows;
};

CDynamicJsonSQLiteDB.cpp

cpp 复制代码
#include "stdafx.h"
#include "DynamicJsonSQLiteDB.h"

//#include "stdafx.h"
//#include "DynamicJsonSQLiteDB.h"
#include <fstream>
#include <sstream>

// SQLite回调函数
int CDynamicJsonSQLiteDB::SQLiteCallback(void* data, int argc, char** argv, char** azColName)
{
    SQueryResult* pResult = static_cast<SQueryResult*>(data);
    std::map<CString, CString> row;

    for (int i = 0; i < argc; i++) {
        CString strColName = CString(azColName[i]);
        CString strValue = argv[i] ? CString(argv[i]) : _T("");
        row[strColName] = strValue;
    }
    pResult->rows.push_back(row);

    return 0;
}

CDynamicJsonSQLiteDB::CDynamicJsonSQLiteDB() : m_pDB(NULL)
{
}

CDynamicJsonSQLiteDB::~CDynamicJsonSQLiteDB()
{
    CloseDB();
}

void CDynamicJsonSQLiteDB::CloseDB()
{
    if (m_pDB) {
        sqlite3_close(m_pDB);
        m_pDB = NULL;
    }
}

CString CDynamicJsonSQLiteDB::ReadJsonFile(LPCTSTR lpszFilePath)
{
    CString strContent;
    CFile file;

    // 使用二进制模式读取,避免编码问题
    if (file.Open(lpszFilePath, CFile::modeRead | CFile::shareDenyNone)) {
        ULONGLONG dwFileLength = file.GetLength();

        if (dwFileLength > 0) {
            // 读取文件内容
            CStringA strContentA;
            char* pBuffer = strContentA.GetBuffer((int)dwFileLength + 1);
            file.Read(pBuffer, (UINT)dwFileLength);
            pBuffer[dwFileLength] = '\0';
            strContentA.ReleaseBuffer();

            // 转换为Unicode
            strContent = CString(strContentA);
        }
        file.Close();
    }
    else {
        m_strLastError.Format(_T("无法打开文件: %s"), lpszFilePath);
    }

    return strContent;
}

BOOL CDynamicJsonSQLiteDB::WriteJsonFile(LPCTSTR lpszFilePath, LPCTSTR lpszContent)
{
    CFile file;

    // 使用二进制模式写入
    if (file.Open(lpszFilePath, CFile::modeCreate | CFile::modeWrite | CFile::shareExclusive)) {
        // 转换为UTF8写入
        CStringA contentA(lpszContent);
        file.Write(contentA, contentA.GetLength());
        file.Close();
        return TRUE;
    }

    m_strLastError.Format(_T("无法写入文件: %s"), lpszFilePath);
    return FALSE;
}

BOOL CDynamicJsonSQLiteDB::ExecuteSQL(LPCTSTR lpszSQL)
{
    if (!m_pDB) {
        m_strLastError = _T("数据库未打开");
        return FALSE;
    }

    char* errorMsg = nullptr;

    // 将Unicode SQL转换为UTF8
    CStringA sqlA(lpszSQL);

    if (sqlite3_exec(m_pDB, sqlA, nullptr, nullptr, &errorMsg) != SQLITE_OK) {
        if (errorMsg) {
            // 将错误信息从UTF8转换为Unicode
            m_strLastError = CString(errorMsg);
            sqlite3_free(errorMsg);
        }
        else {
            m_strLastError = _T("未知SQL错误");
        }
        return FALSE;
    }

    return TRUE;
}

BOOL CDynamicJsonSQLiteDB::TableExists(LPCTSTR lpszTableName)
{
    CString sql;
    sql.Format(_T("SELECT name FROM sqlite_master WHERE type='table' AND name='%s';"), lpszTableName);

    SQueryResult result;
    char* errorMsg = nullptr;
    CStringA sqlA(sql);

    if (sqlite3_exec(m_pDB, sqlA, SQLiteCallback, &result, &errorMsg) != SQLITE_OK) {
        if (errorMsg) sqlite3_free(errorMsg);
        return FALSE;
    }

    return !result.rows.empty();
}

CString CDynamicJsonSQLiteDB::EscapeSQLString(LPCTSTR lpszInput)
{
    /*CString strOutput = lpszInput;
    strOutput.Replace(_T("'"), _T("''"));
    return strOutput;*/

    CString strResult = lpszInput;

    // 先清理字符串
    //strResult.Trim();
    // 首先去除首尾空白
    strResult.Trim();

    //手动挑选去除一些末尾key值的value不对的情况
    strResult.Replace(_T("\r"), _T(""));
    strResult.Replace(_T("\n"), _T(""));
    strResult.Replace(_T("\""), _T(""));
    strResult.Replace(_T("}"), _T(""));
    strResult.Replace(_T("{"), _T(""));

    // 移除常见的JSON转义字符问题
    strResult.Replace(_T("\\\""), _T("\""));  // 转义双引号
    strResult.Replace(_T("\\\\"), _T("\\"));  // 转义反斜杠
    strResult.Replace(_T("\\/"), _T("/"));    // 转义斜杠
    strResult.Replace(_T("\\b"), _T(""));     // 退格符
    strResult.Replace(_T("\\f"), _T(""));     // 换页符
    strResult.Replace(_T("\\n"), _T(""));     // 换行符
    strResult.Replace(_T("\\r"), _T(""));     // 回车符
    strResult.Replace(_T("\\t"), _T(""));     // 制表符

    // 移除控制字符(ASCII < 32)
    CString strCleaned;
    int nLength = strResult.GetLength();

    for (int i = 0; i < nLength; i++) {
        TCHAR ch = strResult[i];
        if (ch >= 32 || ch == _T('\t') || ch == _T('\n') || ch == _T('\r')) {
            strCleaned += ch;
        }
    }



    // 如果字符串被引号包围,去掉它们(但保留转义的内容)
    if (strResult.GetLength() >= 2) {
        // 检查是否被双引号包围
        if (strResult[0] == _T('"') && strResult[strResult.GetLength() - 1] == _T('"')) {
            strResult = strResult.Mid(1, strResult.GetLength() - 2);
        }
        // 检查是否被单引号包围
        else if (strResult[0] == _T('\'') && strResult[strResult.GetLength() - 1] == _T('\'')) {
            strResult = strResult.Mid(1, strResult.GetLength() - 2);
        }
    }

    // 转义SQL特殊字符
    strResult.Replace(_T("'"), _T("''"));
    strResult.Replace(_T("\\"), _T("\\\\"));

    strResult.Trim();

    return strResult;
}

CString CDynamicJsonSQLiteDB::GetCurrentTimestamp()
{
    CTime now = CTime::GetCurrentTime();
    return now.Format(_T("%Y-%m%d %H:%M:%S"));
}


CString CDynamicJsonSQLiteDB::ExtractJsonValue(LPCTSTR lpszJsonData, LPCTSTR lpszKey)
{
    CString strData = lpszJsonData;
    CString strSearch;
    strSearch.Format(_T("\"%s\":\""), lpszKey);

    int nStart = strData.Find(strSearch);
    if (nStart == -1) {
        // 尝试查找不带引号的值
        strSearch.Format(_T("\"%s\":"), lpszKey);
        nStart = strData.Find(strSearch);
        if (nStart == -1) return _T("");

        nStart += strSearch.GetLength();
        int nEnd = strData.Find(_T(","), nStart);
        if (nEnd == -1) nEnd = strData.Find(_T("}"), nStart);
        if (nEnd == -1) return _T("");

        CString strValue = strData.Mid(nStart, nEnd - nStart);
        strValue.Trim();
        // 移除可能的引号
        if (strValue.GetLength() >= 2 && strValue[0] == _T('"') && strValue[strValue.GetLength() - 1] == _T('"')) {
            strValue = strValue.Mid(1, strValue.GetLength() - 2);
        }
        return strValue;
    }

    nStart += strSearch.GetLength();
    int nEnd = strData.Find(_T("\""), nStart);
    if (nEnd == -1) return _T("");

    return strData.Mid(nStart, nEnd - nStart);
}

int CDynamicJsonSQLiteDB::GetNextRecordNum()
{
    CString sql = _T("SELECT MAX(record_num) as max_num FROM PROGRAMAll");
    SQueryResult result;
    char* errorMsg = nullptr;
    CStringA sqlA(sql);

    int nRecordNum = 1;
    if (sqlite3_exec(m_pDB, sqlA, SQLiteCallback, &result, &errorMsg) == SQLITE_OK) {
        if (!result.rows.empty()) {
            CString strMaxNum = result.rows[0][_T("max_num")];
            if (!strMaxNum.IsEmpty()) {
                nRecordNum = _ttoi(strMaxNum) + 1;
            }
        }
    }
    else {
        if (errorMsg) sqlite3_free(errorMsg);
    }

    return nRecordNum;
}

int CDynamicJsonSQLiteDB::GetRecordCount()
{
    CString sql = _T("SELECT COUNT(DISTINCT record_num) as record_count FROM PROGRAMAll");
    SQueryResult result;
    char* errorMsg = nullptr;
    CStringA sqlA(sql);

    int nCount = 0;
    if (sqlite3_exec(m_pDB, sqlA, SQLiteCallback, &result, &errorMsg) == SQLITE_OK) {
        if (!result.rows.empty()) {
            CString strCount = result.rows[0][_T("record_count")];
            if (!strCount.IsEmpty()) {
                nCount = _ttoi(strCount);
            }
        }
    }
    else {
        if (errorMsg) sqlite3_free(errorMsg);
    }

    return nCount;
}

BOOL CDynamicJsonSQLiteDB::ValidateFilePath(LPCTSTR lpszFilePath)
{
    //if (_tcslen(lpszFilePath) == 0) {
    //    return FALSE;
    //}

    //// 检查路径长度
    //if (_tcslen(lpszFilePath) > MAX_PATH - 1) {
    //    return FALSE;
    //}

    //// 检查非法字符
    //CString strInvalidChars = _T("\\/:*?\"<>|");
    //CString strPath = lpszFilePath;

    //for (int i = 0; i < strInvalidChars.GetLength(); i++) {
    //    if (strPath.Find(strInvalidChars[i]) != -1) {
    //        return FALSE;
    //    }
    //}

    //return TRUE;

    if (_tcslen(lpszFilePath) == 0) {
        m_strLastError = _T("文件路径为空");
        return FALSE;
    }

    //// 基本长度检查
    //if (_tcslen(lpszFilePath) > MAX_PATH - 1) {
    //    m_strLastError = _T("文件路径过长");
    //    return FALSE;
    //}

    // 检查文件是否存在(对于输入文件)
    CFileStatus status;
    if (!CFile::GetStatus(lpszFilePath, status)) {
        // 对于输出文件,检查目录是否存在
        CString strPath = lpszFilePath;
        int nLastSlash = strPath.ReverseFind(_T('\\'));
        if (nLastSlash != -1) {
            CString strDir = strPath.Left(nLastSlash);
            DWORD dwAttrib = GetFileAttributes(strDir);
            if (dwAttrib == INVALID_FILE_ATTRIBUTES || !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) {
                m_strLastError = _T("目录不存在: ") + strDir;
                return FALSE;
            }
        }
    }

    return TRUE;
}

CString CDynamicJsonSQLiteDB::GetValidFileName(LPCTSTR lpszFileName)
{
    CString strValidName = lpszFileName;

    // 替换非法字符
    strValidName.Replace(_T("\\"), _T("_"));
    strValidName.Replace(_T("/"), _T("_"));
    strValidName.Replace(_T(":"), _T("_"));
    strValidName.Replace(_T("*"), _T("_"));
    strValidName.Replace(_T("?"), _T("_"));
    strValidName.Replace(_T("\""), _T("_"));
    strValidName.Replace(_T("<"), _T("_"));
    strValidName.Replace(_T(">"), _T("_"));
    strValidName.Replace(_T("|"), _T("_"));

    return strValidName;
}

BOOL CDynamicJsonSQLiteDB::InitializeDBFromJson(LPCTSTR lpszJsonFilePath)
{
    // 验证输入文件路径
    if (!ValidateFilePath(lpszJsonFilePath)) {
        m_strLastError = _T("无效的JSON文件路径");
        return FALSE;
    }

    // 检查JSON文件是否存在
    CFileStatus status;
    if (!CFile::GetStatus(lpszJsonFilePath, status)) {
        m_strLastError.Format(_T("JSON文件不存在: %s"), lpszJsonFilePath);
        return FALSE;
    }

    // 读取JSON文件
    CString strJsonContent = ReadJsonFile(lpszJsonFilePath);
    if (strJsonContent.IsEmpty()) {
        return FALSE;
    }

    // 分析JSON结构
    if (!AnalyzeJsonStructure(strJsonContent)) {
        return FALSE;
    }

    // 生成数据库文件路径
    CString strJsonFile = lpszJsonFilePath;
    CString strDBDirectory;
    CString strDBFileName;

    // 提取目录
    int nLastSlash = strJsonFile.ReverseFind(_T('\\'));
    if (nLastSlash != -1) {
        strDBDirectory = strJsonFile.Left(nLastSlash + 1);
        strDBFileName = strJsonFile.Mid(nLastSlash + 1);
    }
    else {
        strDBDirectory = _T(".\\");
        strDBFileName = strJsonFile;
    }

    // 处理文件名
    int nLastDot = strDBFileName.ReverseFind(_T('.'));
    if (nLastDot != -1) {
        strDBFileName = strDBFileName.Left(nLastDot);
    }

    // 确保文件名有效
    strDBFileName = GetValidFileName(strDBFileName);
    if (strDBFileName.IsEmpty()) {
        strDBFileName = _T("default_database");
    }

    // 构建完整数据库路径
    m_strDBPath = strDBDirectory + strDBFileName + _T(".db");

    // 确保目录存在
    CreateDirectory(strDBDirectory, NULL);

    // 删除已存在的数据库文件(如果需要重新创建)
    // DeleteFile(m_strDBPath);

    // 打开数据库
    CStringA dbPathA(m_strDBPath);

    if (sqlite3_open(dbPathA, &m_pDB) != SQLITE_OK) {
        m_strLastError.Format(_T("无法创建数据库文件: %s\nSQLite错误: %s"),
            m_strDBPath, CString(sqlite3_errmsg(m_pDB)));
        return FALSE;
    }

    // 设置数据库参数
    ExecuteSQL(_T("PRAGMA encoding = 'UTF-8';"));
    ExecuteSQL(_T("PRAGMA foreign_keys = ON;"));
    ExecuteSQL(_T("PRAGMA journal_mode = WAL;"));

    // 创建表结构
    if (!CreateDatabaseTables()) {
        CloseDB();
        return FALSE;
    }

    // 记录成功信息
    CString strSuccessMsg;
    strSuccessMsg.Format(_T("数据库初始化成功:\nJSON文件: %s\n数据库文件: %s"),
        lpszJsonFilePath, m_strDBPath);
    m_strLastError = strSuccessMsg; // 可以改为日志记录

    return TRUE;
}

BOOL CDynamicJsonSQLiteDB::AnalyzeJsonStructure(LPCTSTR lpszJsonData)
{
    // 清空现有结构
    m_tableNames.clear();
    m_tableFields.clear();
    m_subTableFields.clear();

    return ParseJsonObject(lpszJsonData);
}

//BOOL CDynamicJsonSQLiteDB::ParseJsonObject(LPCTSTR lpszJsonData, CString strParentKey)
//{
//    CString strData = lpszJsonData;
//    strData.Trim();
//
//    if (strData.GetLength() < 2 || strData[0] != _T('{') || strData[strData.GetLength() - 1] != _T('}')) {
//        m_strLastError = _T("无效的JSON格式");
//        return FALSE;
//    }
//
//    // 移除外层大括号
//    CString strContent = strData.Mid(1, strData.GetLength() - 2);
//    strContent.Trim();
//
//    int nPos = 0;
//
//    while (nPos < strContent.GetLength()) {
//        // 查找键
//        int nKeyStart = strContent.Find(_T('"'), nPos);
//        if (nKeyStart == -1) break;
//
//        int nKeyEnd = strContent.Find(_T('"'), nKeyStart + 1);
//        if (nKeyEnd == -1) break;
//
//        CString strKey = strContent.Mid(nKeyStart + 1, nKeyEnd - nKeyStart - 1);
//
//        // 查找冒号
//        int nColonPos = strContent.Find(_T(':'), nKeyEnd + 1);
//        if (nColonPos == -1) break;
//
//        // 查找值开始位置
//        int nValueStart = nColonPos + 1;
//        while (nValueStart < strContent.GetLength() &&
//            (strContent[nValueStart] == _T(' ') || strContent[nValueStart] == _T('\t'))) {
//            nValueStart++;
//        }
//
//        if (nValueStart >= strContent.GetLength()) break;
//
//        // 判断值类型
//        if (strContent[nValueStart] == _T('{')) {
//            // 对象类型 - 递归解析
//            int nBraceCount = 1;
//            int nValueEnd = nValueStart + 1;
//
//            while (nValueEnd < strContent.GetLength() && nBraceCount > 0) {
//                if (strContent[nValueEnd] == _T('{')) nBraceCount++;
//                else if (strContent[nValueEnd] == _T('}')) nBraceCount--;
//                nValueEnd++;
//            }
//
//            if (nBraceCount != 0) break;
//
//            CString strSubContent = strContent.Mid(nValueStart, nValueEnd - nValueStart);
//
//            if (strParentKey.IsEmpty()) {
//                // 顶级表(PROGRAM1, PROGRAM2等)
//                m_tableNames.push_back(strKey);
//                m_subTableFields[strKey] = std::map<CString, std::vector<CString>>();
//                ParseJsonObject(strSubContent, strKey);
//            }
//            else {
//                // 子表(P1Model1, P1Model2等)
//                m_subTableFields[strParentKey][strKey] = std::vector<CString>();
//                ParseJsonObject(strSubContent, strParentKey + _T(".") + strKey);
//            }
//
//            nPos = nValueEnd;
//        }
//        else if (strContent[nValueStart] == _T('"')) {
//            // 字符串值 - 字段
//            int nValueEnd = strContent.Find(_T('"'), nValueStart + 1);
//            if (nValueEnd == -1) break;
//
//            if (!strParentKey.IsEmpty()) {
//                // 添加到对应的表或子表
//                if (strParentKey.Find(_T('.')) == -1) {
//                    // 主表字段
//                    m_tableFields[strParentKey].push_back(strKey);
//                }
//                else {
//                    // 子表字段
//                    CString strMainTable = strParentKey.Left(strParentKey.Find(_T('.')));
//                    CString strSubTable = strParentKey.Mid(strParentKey.Find(_T('.')) + 1);
//                    m_subTableFields[strMainTable][strSubTable].push_back(strKey);
//                }
//            }
//
//            nPos = nValueEnd + 1;
//        }
//        else {
//            // 其他类型(数字、布尔值等)
//            int nValueEnd = strContent.Find(_T(','), nValueStart);
//            if (nValueEnd == -1) nValueEnd = strContent.Find(_T('}'), nValueStart );
//            if (nValueEnd == -1) break;
//
//            if (!strParentKey.IsEmpty()) {
//                // 添加到对应的表或子表
//                if (strParentKey.Find(_T('.')) == -1) {
//                    // 主表字段
//                    m_tableFields[strParentKey].push_back(strKey);
//                }
//                else {
//                    // 子表字段
//                    CString strMainTable = strParentKey.Left(strParentKey.Find(_T('.')));
//                    CString strSubTable = strParentKey.Mid(strParentKey.Find(_T('.')) + 1);
//                    m_subTableFields[strMainTable][strSubTable].push_back(strKey);
//                }
//            }
//
//            nPos = nValueEnd;
//        }
//
//        // 跳过逗号
//        if (nPos < strContent.GetLength() && strContent[nPos] == _T(',')) nPos++;
//    }
//
//    return TRUE;
//}





BOOL CDynamicJsonSQLiteDB::ParseJsonObject(LPCTSTR lpszJsonData, CString strParentKey)
{
    CString strData = lpszJsonData;
    strData.Trim();

    if (strData.GetLength() < 2 || strData[0] != _T('{') || strData[strData.GetLength() - 1] != _T('}')) {
        m_strLastError = _T("无效的JSON格式");
        return FALSE;
    }

    // 移除外层大括号
    CString strContent = strData.Mid(1, strData.GetLength() - 2);
    strContent.Trim();

    int nPos = 0;
    int nLength = strContent.GetLength();

    while (nPos < nLength) {
        // 查找键
        int nKeyStart = strContent.Find(_T('"'), nPos);
        if (nKeyStart == -1) break;

        int nKeyEnd = strContent.Find(_T('"'), nKeyStart + 1);
        if (nKeyEnd == -1) break;

        CString strKey = strContent.Mid(nKeyStart + 1, nKeyEnd - nKeyStart - 1);

        // 查找冒号
        int nColonPos = strContent.Find(_T(':'), nKeyEnd + 1);
        if (nColonPos == -1) break;

        // 查找值开始位置
        int nValueStart = nColonPos + 1;
        while (nValueStart < nLength &&
            (strContent[nValueStart] == _T(' ') ||
                strContent[nValueStart] == _T('\t') ||
                strContent[nValueStart] == _T('\r') ||
                strContent[nValueStart] == _T('\n'))) {
            nValueStart++;
        }

        if (nValueStart >= nLength) break;

        TCHAR chValueStart = strContent[nValueStart];

        // 判断值类型
        if (chValueStart == _T('{')) {
            // 对象类型 - 递归解析
            int nBraceCount = 1;
            int nValueEnd = nValueStart + 1;

            while (nValueEnd < nLength && nBraceCount > 0) {
                if (strContent[nValueEnd] == _T('{')) nBraceCount++;
                else if (strContent[nValueEnd] == _T('}')) nBraceCount--;
                nValueEnd++;
            }

            if (nBraceCount != 0) break;

            CString strSubContent = strContent.Mid(nValueStart, nValueEnd - nValueStart);

            if (strParentKey.IsEmpty()) {
                // 顶级表(PROGRAM1, PROGRAM2等)
                m_tableNames.push_back(strKey);
                m_subTableFields[strKey] = std::map<CString, std::vector<CString>>();
                ParseJsonObject(strSubContent, strKey);
            }
            else {
                // 子表(P1Model1, P1Model2等)
                m_subTableFields[strParentKey][strKey] = std::vector<CString>();
                ParseJsonObject(strSubContent, strParentKey + _T(".") + strKey);
            }

            nPos = nValueEnd;
        }
        else if (chValueStart == _T('"')) {
            // 字符串值 - 字段
            int nValueEnd = strContent.Find(_T('"'), nValueStart + 1);
            if (nValueEnd == -1) break;

            if (!strParentKey.IsEmpty()) {
                AddFieldToTable(strParentKey, strKey);
            }

            nPos = nValueEnd + 1;
        }
        else {
            // 其他类型(数字、布尔值、null等)
            int nValueEnd = nValueStart;

            // 遍历直到找到逗号、大括号或行尾
            while (nValueEnd < nLength) {
                TCHAR ch = strContent[nValueEnd];
                if (ch == _T(',') || ch == _T('}') || ch == _T(' ')) {
                    break;
                }
                nValueEnd++;
            }

            // 提取值内容(用于调试)
            CString strValue = strContent.Mid(nValueStart, nValueEnd - nValueStart);
            strValue.Trim();

            if (!strParentKey.IsEmpty()) {
                AddFieldToTable(strParentKey, strKey);
            }

            nPos = nValueEnd;
        }

        // 跳过逗号和空白
        while (nPos < nLength &&
            (strContent[nPos] == _T(',') ||
                strContent[nPos] == _T(' ') ||
                strContent[nPos] == _T('\t') ||
                strContent[nPos] == _T('\r') ||
                strContent[nPos] == _T('\n'))) {
            nPos++;
        }
    }

    return TRUE;
}

// 辅助函数:添加字段到对应的表
void CDynamicJsonSQLiteDB::AddFieldToTable(const CString& strParentKey, const CString& strFieldName)
{
    if (strParentKey.Find(_T('.')) == -1) {
        // 主表字段
        m_tableFields[strParentKey].push_back(strFieldName);
    }
    else {
        // 子表字段
        CString strMainTable = strParentKey.Left(strParentKey.Find(_T('.')));
        CString strSubTable = strParentKey.Mid(strParentKey.Find(_T('.')) + 1);
        m_subTableFields[strMainTable][strSubTable].push_back(strFieldName);
    }
}







BOOL CDynamicJsonSQLiteDB::CreateDatabaseTables()
{
    // 创建总表PROGRAMAll
    CString sql = _T("CREATE TABLE IF NOT EXISTS PROGRAMAll (");
    sql += _T("id INTEGER PRIMARY KEY AUTOINCREMENT, ");
    sql += _T("record_num INTEGER NOT NULL, ");
    sql += _T("table_name TEXT NOT NULL, ");
    sql += _T("field_path TEXT NOT NULL, ");  // 字段路径:表.子表.字段
    sql += _T("field_value TEXT, "); 
    //sql += _T("created_time TEXT DEFAULT CURRENT_TIMESTAMP");// 时间,这个不准
    sql += _T("created_time TEXT DEFAULT (datetime('now', 'localtime'))");  // 使用本地时间
    sql += _T(");");

    if (!ExecuteSQL(sql)) {
        return FALSE;
    }

    // 为每个主表创建对应的数据库表
    for (const auto& tableName : m_tableNames) {
        CString sql = _T("CREATE TABLE IF NOT EXISTS ") + tableName + _T(" (");
        sql += _T("id INTEGER PRIMARY KEY AUTOINCREMENT, ");
        sql += _T("record_num INTEGER NOT NULL, ");
        //sql += _T("created_time TEXT DEFAULT CURRENT_TIMESTAMP");     //这个时间不准
        sql += _T("created_time TEXT DEFAULT (datetime('now', 'localtime'))");  // 使用本地时间

        // 添加所有字段(扁平化结构)
        for (const auto& subTablePair : m_subTableFields[tableName]) {
            for (const auto& fieldName : subTablePair.second) {
                CString strFieldPath = subTablePair.first + _T("_") + fieldName;
                sql += _T(", ") + strFieldPath + _T(" TEXT");
            }
        }

        sql += _T(");");

        if (!ExecuteSQL(sql)) {
            return FALSE;
        }
    }

    return TRUE;
}

// 修改后的AddDataRecord函数 - 传入JSON文件名
BOOL CDynamicJsonSQLiteDB::AddDataRecord(LPCTSTR lpszJsonFilePath)
{
    if (!m_pDB) {
        m_strLastError = _T("数据库未初始化");
        return FALSE;
    }

    // 获取下一个记录编号
    int nRecordNum = GetNextRecordNum();

    // 从文件插入数据
    return InsertJsonFromFile(lpszJsonFilePath, nRecordNum);
}

// 新增:从JSON文件插入数据
BOOL CDynamicJsonSQLiteDB::InsertJsonFromFile(LPCTSTR lpszJsonFilePath, int nRecordNum)
{
    // 读取JSON文件
    CString strJsonContent = ReadJsonFile(lpszJsonFilePath);
    if (strJsonContent.IsEmpty()) {
        m_strLastError.Format(_T("无法读取JSON文件: %s"), lpszJsonFilePath);
        return FALSE;
    }

    // 验证JSON结构是否与初始化时一致
    if (!ValidateJsonStructure(strJsonContent)) {
        m_strLastError = _T("JSON文件结构与初始化时不一致");
        return FALSE;
    }

    // 插入数据
    return InsertJsonData(strJsonContent, nRecordNum);
}

// 新增:验证JSON结构是否一致
BOOL CDynamicJsonSQLiteDB::ValidateJsonStructure(LPCTSTR lpszJsonData)
{
    // 临时存储解析出的结构
    std::vector<CString> tempTableNames;
    std::map<CString, std::map<CString, std::vector<CString>>> tempSubTableFields;

    // 解析JSON结构
    CString strData = lpszJsonData;
    strData.Trim();

    if (strData.GetLength() < 2 || strData[0] != _T('{') || strData[strData.GetLength() - 1] != _T('}')) {
        return FALSE;
    }

    // 这里简化验证,实际应该完整解析并比较结构
    // 检查是否包含所有必需的表
    for (const auto& tableName : m_tableNames) {
        CString strSearch;
        strSearch.Format(_T("\"%s\":"), tableName);
        if (strData.Find(strSearch) == -1) {
            return FALSE;
        }
    }

    return TRUE;
}

BOOL CDynamicJsonSQLiteDB::InsertJsonData(LPCTSTR lpszJsonData, int nRecordNum)
{
    // 提取所有字段值
    std::map<CString, CString> fieldValues;
    ExtractAllFieldsFromJson(lpszJsonData, fieldValues);

    CString strCurrentTime = GetCurrentTimestamp();

    // 为每个主表插入数据
    for (const auto& tableName : m_tableNames) {
        // 构建INSERT语句
        CString sql = _T("INSERT INTO ") + tableName + _T(" (record_num");
        CString values = _T(" VALUES (") + CString(std::to_string(nRecordNum).c_str());

        // 添加字段值
        for (const auto& subTablePair : m_subTableFields[tableName]) {
            for (const auto& fieldName : subTablePair.second) {
                CString strFieldPath = subTablePair.first + _T("_") + fieldName;
                CString strFullPath = tableName + _T(".") + subTablePair.first + _T(".") + fieldName;

                sql += _T(", ") + strFieldPath;

                if (fieldValues.find(strFullPath) != fieldValues.end()) {
                    values += _T(", '") + EscapeSQLString(fieldValues[strFullPath]) + _T("'");

                    // 插入到总表
                    CString allSql;
                    //allSql.Format(_T("INSERT INTO PROGRAMAll (record_num, created_time, table_name, field_path, field_value ) VALUES (%d, '%s', '%s', '%s', '%s')"),
                    //    nRecordNum, strCurrentTime, tableName, strFullPath, EscapeSQLString(fieldValues[strFullPath]));

                    allSql.Format(_T("INSERT INTO PROGRAMAll (record_num, table_name, field_path, field_value ) VALUES (%d, '%s', '%s', '%s')"),
                        nRecordNum, tableName, strFullPath, EscapeSQLString(fieldValues[strFullPath]));

                    ExecuteSQL(allSql);
                }
                else {
                    values += _T(", NULL");
                }
            }
        }

        sql += _T(")");
        values += _T(")");
        sql += values;

        if (!ExecuteSQL(sql)) {
            return FALSE;
        }
    }

    return TRUE;
}
//
//BOOL CDynamicJsonSQLiteDB::InsertJsonData(LPCTSTR lpszJsonData, int nRecordNum)
//{
//    std::map<CString, CString> fieldValues;
//    ExtractAllFieldsFromJson(lpszJsonData, fieldValues);
//
//    for (const auto& tableName : m_tableNames) {
//        CString sql = _T("INSERT INTO ") + tableName + _T(" (record_num");
//        CString values = _T(" VALUES (") + CString(std::to_string(nRecordNum).c_str());
//
//        for (const auto& subTablePair : m_subTableFields[tableName]) {
//            for (const auto& fieldName : subTablePair.second) {
//                CString strFieldPath = subTablePair.first + _T("_") + fieldName;
//                CString strFullPath = tableName + _T(".") + subTablePair.first + _T(".") + fieldName;
//
//                sql += _T(", ") + strFieldPath;
//
//                auto it = fieldValues.find(strFullPath);
//                if (it != fieldValues.end()) {
//                    // 清理字段值
//                    CString cleanedValue = it->second;
//                    cleanedValue.Trim();
//
//                    // 移除可能的尾部垃圾字符
//                    while (cleanedValue.GetLength() > 0 &&
//                        (cleanedValue[cleanedValue.GetLength() - 1] == _T('"') ||
//                            cleanedValue[cleanedValue.GetLength() - 1] == _T('}') ||
//                            cleanedValue[cleanedValue.GetLength() - 1] == _T(' '))) {
//                        cleanedValue = cleanedValue.Left(cleanedValue.GetLength() - 1);
//                    }
//
//                    CString escapedValue = EscapeSQLString(cleanedValue);
//                    values += _T(", '") + escapedValue + _T("'");
//
//                    // 插入到总表
//                    CString allSql;
//                    allSql.Format(_T("INSERT INTO PROGRAMAll (record_num, table_name, field_path, field_value) VALUES (%d, '%s', '%s', '%s')"),
//                        nRecordNum, tableName, strFullPath, escapedValue);
//                    ExecuteSQL(allSql);
//                }
//                else {
//                    values += _T(", NULL");
//                }
//            }
//        }
//
//        sql += _T(")");
//        values += _T(")");
//        sql += values;
//
//        if (!ExecuteSQL(sql)) {
//            return FALSE;
//        }
//    }
//
//    return TRUE;
//}
void CDynamicJsonSQLiteDB::ExtractAllFieldsFromJson(LPCTSTR lpszJsonData, std::map<CString, CString>& fieldValues)
{
    CString strData = lpszJsonData;

    // 遍历所有表结构来提取字段值
    for (const auto& tableName : m_tableNames) {
        for (const auto& subTablePair : m_subTableFields[tableName]) {
            for (const auto& fieldName : subTablePair.second) {
                CString strFullPath = tableName + _T(".") + subTablePair.first + _T(".") + fieldName;
                CString strValue = ExtractJsonValue(lpszJsonData, fieldName);

                if (!strValue.IsEmpty()) {
                    fieldValues[strFullPath] = strValue;
                }
            }
        }
    }
}

BOOL CDynamicJsonSQLiteDB::ExportDataToJson(int nRecordNum, LPCTSTR lpszOutputJsonFile)
{
    if (!m_pDB) {
        m_strLastError = _T("数据库未初始化");
        return FALSE;
    }

    CString strJsonContent = GenerateJsonFromData(nRecordNum);
    if (strJsonContent.IsEmpty()) {
        return FALSE;
    }

    return WriteJsonFile(lpszOutputJsonFile, strJsonContent);
}

CString CDynamicJsonSQLiteDB::GenerateJsonFromData(int nRecordNum)
{
    CString strJson = _T("{\r\n");

    // 为每个表生成JSON结构
    for (size_t i = 0; i < m_tableNames.size(); i++) {
        if (!BuildJsonForTable(strJson, m_tableNames[i], nRecordNum)) {
            return _T("");
        }

        if (i < m_tableNames.size() - 1) {
            strJson += _T(",\r\n\r\n");
        }
    }

    strJson += _T("\r\n}");

    return strJson;
}

BOOL CDynamicJsonSQLiteDB::BuildJsonForTable(CString& strJson, LPCTSTR lpszTableName, int nRecordNum)
{
    // 查询指定记录的数据
    CString sql;
    sql.Format(_T("SELECT * FROM %s WHERE record_num = %d"), lpszTableName, nRecordNum);

    SQueryResult result;
    char* errorMsg = nullptr;
    CStringA sqlA(sql);

    if (sqlite3_exec(m_pDB, sqlA, SQLiteCallback, &result, &errorMsg) != SQLITE_OK) {
        if (errorMsg) {
            m_strLastError = CString(errorMsg);
            sqlite3_free(errorMsg);
        }
        return FALSE;
    }

    if (result.rows.empty()) {
        m_strLastError.Format(_T("未找到记录编号 %d 的数据"), nRecordNum);
        return FALSE;
    }

    std::map<CString, CString> rowData = result.rows[0];

    // 构建JSON结构
    strJson += _T("\t\"") + CString(lpszTableName) + _T("\": {\r\n");

    // 添加子表
    const auto& subTables = m_subTableFields[lpszTableName];
    int subTableCount = 0;
    for (const auto& subTablePair : subTables) {
        strJson += _T("\t\t\"") + subTablePair.first + _T("\":{\r\n");

        // 添加字段
        const auto& fields = subTablePair.second;
        int fieldCount = 0;
        for (const auto& fieldName : fields) {
            CString strFieldPath = subTablePair.first + _T("_") + fieldName;
            CString strValue = _T("\"\"");

            if (rowData.find(strFieldPath) != rowData.end() && !rowData[strFieldPath].IsEmpty()) {
                strValue = _T("\"") + rowData[strFieldPath] + _T("\"");
            }

            strJson += _T("\t\t\t\"") + fieldName + _T("\":") + strValue;

            if (++fieldCount < fields.size()) {
                strJson += _T(",");
            }
            strJson += _T("\r\n");
        }

        strJson += _T("\t\t}");

        if (++subTableCount < subTables.size()) {
            strJson += _T(",");
        }
        strJson += _T("\r\n");
    }

    strJson += _T("\t}");

    return TRUE;
}
相关推荐
WoodWall5 小时前
WebServer 00 重要前置知识
c++·后端
FFZero15 小时前
【C++/Lua联合开发】 (一) Lua基础知识
c++·音视频·lua
墨尘笔尖5 小时前
使用子进程实现 C++ 与 Python 交互式控制台
c++·windows·python
喜欢吃燃面5 小时前
算法中的链表结构
开发语言·c++·学习·算法
十五年专注C++开发5 小时前
Fruit框架:C++依赖注入解决方案
开发语言·c++·依赖注入·fruit框架
Juan_20126 小时前
P1041题解
c++·算法·题解·搜索
YaoYuan93236 小时前
Ubuntu22.04 中搭建基于 Qemu 的内核(驱动)开发环境
数据库
hans汉斯6 小时前
【计算机科学与应用】基于多光谱成像与边缘计算的物流安全风险预警模式及系统实现
大数据·数据库·人工智能·设计模式·机器人·边缘计算·论文笔记
冷崖6 小时前
const 与 constexpr
c++·学习