首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

C++ JSON 庫 jsoncpp 避坑指南:Assert 崩潰、數組訪問、類型轉換與嚴格模式

     編輯:C++ 入門

背景

jsoncpp 是 C++ 常用 JSON 庫,但其錯誤處理機制依賴 assert,在 Linux 下觸發會調用 abort() 導致進程崩潰(收到 SIGABRT),對服務端極其危險。本文總結常見崩潰場景與規避方案。

三大崩潰場景及解決方案

1. 非法 JSON 字符串導致自動容錯為字符串類型

現象:解析 "1111 {}" 這類非法 JSON,jsoncpp 不報錯而是將其視為字符串。隨後調用 value["key"] 或 value[index] 觸發 assert(type_ == nullValue || type_ == objectValue) 崩潰。

解決:啟用嚴格模式,非法 JSON 直接返回 false:

Json::Reader reader(Json::Features::strictMode());
if (!reader.parse(str, value)) { /* 處理錯誤 */ }

2. 直接對 JSON 數組用鍵訪問

現象:JSON 中 "friends": [{"name":"A"},{"name":"B"}] 是數組。代碼 value["friends"]["name"] 嘗試用字符串鍵訪問數組,觸發同類 assert。

解決:先取數組對象,再遍歷索引訪問:

Json::Value friends = value["friends"];
for (int i = 0; i < friends.size(); ++i)
    cout << friends[i]["name"].asString();

3. 類型轉換不匹配

現象:JSON 值為字符串 "age":"24",代碼 value["age"].asInt() 強制轉整數,觸發 assert。

解決:先判斷類型再轉換:

if (value["age"].isInt()) int age = value["age"].asInt();
else if (value["age"].isString()) int age = stoi(value["age"].asString());

jsoncpp 讀寫最佳實踐代碼模板

讀取(含嚴格模式、類型檢查、數組遍歷)

#include 
#include 
#include 
using namespace std;

int main() {
    Json::Reader reader(Json::Features::strictMode());
    string str = "{\"name\":\"tom\",\"age\":\"24\",\"friends\":[{\"name\":\"A\"},{\"name\":\"B\"}]}";
    Json::Value root;
    if (!reader.parse(str, root)) { cerr << "parse error\n"; return -1; }

    string name = root["name"].asString();
    int age = 0;
    if (root["age"].isInt()) age = root["age"].asInt();
    else if (root["age"].isString()) age = stoi(root["age"].asString());

    Json::Value friends = root["friends"];
    for (int i = 0; i < friends.size(); ++i)
        cout << friends[i]["name"].asString() << endl;

    return 0;
}

寫入(FastWriter 輸出緊湊格式)

#include 
#include 
#include 
using namespace std;

int main() {
    Json::Value root;
    Json::FastWriter writer;
    Json::Value person;
    person["name"] = "hello world";
    person["age"] = 100;
    root.append(person);

    string json_str = writer.write(root);
    ofstream ofs("out.json");
    assert(ofs.is_open());
    ofs << json_str;
    return 0;
}

服務端選型建議

因 jsoncpp 依賴 assert、非法輸入易崩潰,且 SDK 接入多為 PHP/Python 生態,建議:

  • 網關層用 Nginx + Lua (OpenResty) 或 Python 做 JSON 校驗與解析。
  • C++ 核心邏輯僅處理已驗證的結構化數據(如 protobuf/flatbuffers)。
  • 若必須在 C++ 用 JSON,考慮 nlohmann/json(異常機制而非 assert)或 rapidjson(無異常、高性能)。

總結

jsoncpp 功能完整但錯誤處理機制不適合高可用服務端。必須:

  1. 啟用 strictMode 拒絕非法 JSON。
  2. 訪問前檢查 isArray()/isObject()/isInt() 等類型。
  3. 數組必須用索引遍歷,不可用鍵訪問。
  4. 考慮替換為更健壯的現代 JSON 庫。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved