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

【问题】Qt c++ 因编码问题解析json失败

问题

项目上遇到一个很离谱的问题,json如下:

{
	"Place": "北滘"
}

这是一个正常的json,他的编码是GB2312,可是我的代码在解析json时报错,代码如下:

// 判断是否为GB2312编码
bool isGb2312(const QByteArray &data) {
    QTextCodec *codec = QTextCodec::codecForName("GB2312");
    if (!codec)
        return false;

    QString decodedString = codec->toUnicode(data);
    QByteArray encodedData = codec->fromUnicode(decodedString);

    return data == encodedData;
}
	
	QJsonParseError parseError;

bool ParseJsonVerson(QByteArray pBody, QString &strErrMsg){

    if(isGb2312(fileJsonData)){
        QTextCodec *codec = QTextCodec::codecForName("GB2312");
        if (codec) 
            pBody = codec->toUnicode(pBody).toUtf8();
    }

    QJsonDocument jsonDoc = QJsonDocument::fromJson(pBody, &parseError);
    if (jsonDoc.isNull()) {
        bRet = false;
        strErrMsg = "解析失败,不是完整的json11!";
        qWarning() << "Failed to create JSON document:" << parseError.errorString();
        return bRet;
    }
    
    //json处理....
}

这里运行时,jsonDoc.isNull()=true
一脸懵逼,没办法单步进去查看,发现它判断的json编码不是"GB2312"
!!!!
继续查,发现我把“滘”字删掉就正常了!???
直接定位“滘”字细节如下:
单纯的“滘” 他的16进制数据是 0x9C 0xF2
在这里插入图片描述

调用bool isGb2312(const QByteArray &data)接口:
在这里插入图片描述
这里明显发现不对了,转换回来失败了!

我们使用“好”字再来测试:
在这里插入图片描述

QString decodedString = codec->toUnicode(data);做了什么?

QTextCodec::toUnicode

QTextCodec::toUnicode 方法的实现涉及将字节数组(QByteArray)转换为 QString。在 Qt 中,QTextCodec 是一个抽象类,负责处理不同字符编码之间的转换。具体到 GB2312 编码,toUnicode 方法的实现过程大致如下:

  1. 字节解析:首先,toUnicode 方法会读取输入的字节数组,并根据 GB2312 编码的规则解析字节。GB2312 是一个双字节编码,字符的表示通常由两个字节组成。

  2. 字符映射:对于每一对字节,toUnicode 会查找 GB2312 字符集中的对应字符。如果字节对在 GB2312 字符集中存在,则返回相应的 Unicode 字符。

  3. 错误处理:如果输入的字节数组包含无效的字节序列(例如,单独的字节或不在 GB2312 字符集中的字节对),toUnicode 方法会返回一个替代字符(通常是 U+FFFD,即 “�”),表示无法识别的字符。这就是你在调用 toUnicode 时得到 0xFFFD 的原因。

返回结果:最后,toUnicode 方法将所有有效的字符组合成一个 QString 并返回。

问题定位了,QTextCodec::toUnicode 没能成功将“滘”字转换成Unicode。查询了一下GB2312字符集中没有“滘”这个字‌!!!
0x9C 0xF2 编码表示的是汉字“滘”,属于GBK编码!!!

解决办法:

 // 检测文件编码
 QString detectEncoding(QByteArray data) {

    if (isUtf8(data)) {
        return "UTF-8";
    } else if (isGb2312(data)) {
        return "GB2312";
    } else if (isGbkEncoded(data)){
        return "GBK";
    }
    else {
        return "Unknown";
    }
}
bool ParseJsonVerson(QByteArray pBody, QString &strErrMsg){
	if(strCode=="Unknown"){
        strErrMsg = "解析失败,未知编码!";
        qWarning() << "Failed to create JSON document:" << parseError.errorString();
        return bRet;
    }
    else if(strCode=="GB2312"){
        QTextCodec *codec = QTextCodec::codecForName("GB2312");
        if (codec) {
            pBody = codec->toUnicode(pBody).toUtf8();
        }
    }
    else if(strCode=="GBK"){
        QTextCodec *codec = QTextCodec::codecForName("GBK");
        if (codec) {
            pBody = codec->toUnicode(pBody).toUtf8();
        }
    }
      QJsonDocument jsonDoc = QJsonDocument::fromJson(pBody, &parseError);
    if (jsonDoc.isNull()) {
        bRet = false;
        strErrMsg = "解析失败,不是完整的json11!";
        qWarning() << "Failed to create JSON document:" << parseError.errorString();
        return bRet;
    }
    
    //json处理....
}

注:如果咱之前统一编码,全部用UTF8也就没这茬儿了。总结,蛋疼。


http://www.kler.cn/a/556464.html

相关文章:

  • 多环境日志管理:使用Logback与Logstash集成实现高效日志处理
  • 《炒股养家心法.pdf》 kimi总结
  • 腾讯云开源Deepseek-V3与R1大模型API免费使用 + Chatbox本地化部署指南:从零到一的AI探索之旅
  • stm32单片机个人学习笔记16(SPI通信协议)
  • 论文解读 | AAAI'25 Cobra:多模态扩展的大型语言模型,以实现高效推理
  • ZLG嵌入式笔记 | 为什么你的网卡工作会不正常?(中)
  • Mysql测试连接失败
  • 【Day45 LeetCode】图论问题 Ⅲ
  • 为什么要用 const 和 let,而不是 var?
  • 使用 Docker 部署 Apache Spark 集群教程
  • 2025寒假天梯训练7
  • Python应用算法之贪心算法理解和实践
  • [Android] Battery Guru - 手机电量管理优化
  • 【愚公系列】《Python网络爬虫从入门到精通》022-Splash的爬虫应用
  • 后“智驾平权”时代,谁为安全冗余和体验升级“买单”
  • 跳表的C语言实现
  • Java还是网络安全 java 网络安全面试题
  • 杰和科技GAM-AI视觉识别管理系统,让AI走进零售营销
  • 【算法与数据结构】字典树(Trie)详解
  • 火语言RPA--Excel插入空列