C++使用nlohmann/json庫解析和處理JSON數(shù)據(jù)的操作指南
1. nlohmann/json庫介紹
nlohmann/json 是一個用于現(xiàn)代C++的JSON庫,由Niels Lohmann開發(fā)。它是一個單頭文件庫,使用C++11標(biāo)準(zhǔn)編寫,具有以下特點:
- 簡潔的API:語法直觀,像訪問原生C++數(shù)據(jù)結(jié)構(gòu)一樣操作JSON
- 類型安全:提供了類型檢查和異常處理機制
- 高性能:比許多其他JSON庫更快
- 零依賴:只需要包含一個頭文件即可使用
- 跨平臺:支持Windows、Linux、macOS等操作系統(tǒng)
1.1 下載安裝
nlohmann/json庫可以通過多種方式獲取和安裝:
通過包管理器安裝:
- vcpkg:
vcpkg install nlohmann-json - Conan:
conan install nlohmann_json/3.11.2 - apt (Ubuntu/Debian):
sudo apt install nlohmann-json3-dev
手動下載:
- 訪問GitHub倉庫:https://github.com/nlohmann/json
- 下載單頭文件版本:https://github.com/nlohmann/json/releases
- 將
json.hpp文件復(fù)制到項目目錄中
1.2 配置方法
在項目中使用nlohmann庫非常簡單:
包含頭文件:
#include <nlohmann/json.hpp> // 或者使用別名 using json = nlohmann::json;
CMake配置(如果通過包管理器安裝):
find_package(nlohmann_json CONFIG REQUIRED) target_link_libraries(main PRIVATE nlohmann_json::nlohmann_json)
手動配置:
- 將
json.hpp文件放在項目目錄中 - 在代碼中包含:
#include "nlohmann/json.hpp"
在本項目中,我們直接將json.hpp文件包含在項目中,無需額外配置。
2. 應(yīng)用場景
在本項目中,nlohmann庫主要應(yīng)用于以下場景:
2.1 解析HTTP響應(yīng)中的JSON數(shù)據(jù)
當(dāng)客戶端向服務(wù)器發(fā)送GET或POST請求后,服務(wù)器返回的數(shù)據(jù)通常是JSON格式。我們需要使用nlohmann/json庫來解析這些數(shù)據(jù),提取有用信息。
2.2 格式化JSON數(shù)據(jù)用于展示
為了在WebView中更好地展示JSON數(shù)據(jù),我們需要將其格式化為帶有語法高亮的HTML格式。
2.3 構(gòu)造JSON請求數(shù)據(jù)
在向服務(wù)器發(fā)送POST請求時,我們需要構(gòu)造JSON格式的請求體數(shù)據(jù)。
2.4 處理文件列表等結(jié)構(gòu)化數(shù)據(jù)
服務(wù)器返回的文件列表等信息通常以JSON數(shù)組形式提供,需要使用nlohmann庫進行解析和處理。
3. 使用JsonHandler封裝nlohmann/json庫相關(guān)方法
為了更好地管理和重用JSON處理代碼,我們創(chuàng)建了JsonHandler類來封裝所有與nlohmann/json庫相關(guān)的操作。
3.1 JsonHandler.h頭文件
#ifndef JSONHANDLER_H
#define JSONHANDLER_H
#include <wx/string.h>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
class JsonHandler {
public:
JsonHandler();
~JsonHandler();
// JSON處理相關(guān)方法
void ParseJsonResponse(const std::string& response);
wxString FormatJsonForHtml(const wxString& jsonStr, const bool& formatBit);
wxString FormatJsonValue(const json& j);
wxString FormatJsonValueFormat(const json& j, int indentLevel);
wxString GenerateJsonHtml(const wxString& jsonResponse, const bool& formatBit);
// 保存原始JSON數(shù)據(jù)
void SetRawJsonData(const wxString& rawData) { m_rawJsonData = rawData; }
wxString GetRawJsonData() const { return m_rawJsonData; }
private:
wxString m_rawJsonData; // 保存原始JSON數(shù)據(jù)
};
#endif // JSONHANDLER_H
3.2 JsonHandler.cpp實現(xiàn)文件
JsonHandler.cpp文件中實現(xiàn)了所有JSON處理方法:
- ParseJsonResponse:解析JSON響應(yīng)數(shù)據(jù)
- FormatJsonForHtml:將JSON格式化為HTML顯示格式
- FormatJsonValue:遞歸生成不帶縮進的JSON HTML字符串
- FormatJsonValueFormat:遞歸生成帶縮進的JSON HTML字符串
- GenerateJsonHtml:生成完整的JSON顯示HTML頁面
下面是這些方法的具體實現(xiàn):
3.2.1 ParseJsonResponse方法實現(xiàn)
// 解析 JSON 響應(yīng)
void JsonHandler::ParseJsonResponse(const std::string& response) {
// 嘗試解析 JSON
try {
// 使用nlohmann庫解析JSON字符串
json j = json::parse(response);
// 將 JSON 格式化為帶縮進的字符串
std::string json_str = j.dump(4);
// 記錄日志
wxLogInfo(wxString::FromUTF8("JSON: %s"), wxString::FromUTF8(json_str.c_str()));
// 檢查是否存在 "message" 字段
if (j.contains("message")) {
// 獲取message字段的值
std::string message = j["message"];
// 記錄解析結(jié)果到日志
wxLogInfo(wxString::FromUTF8("解析結(jié)果: %s"), wxString::FromUTF8(message.c_str()));
} else {
// 如果缺少message字段,記錄錯誤日志
wxLogInfo(wxString::FromUTF8("JSON格式錯誤: 缺少message字段"));
}
// 檢查是否存在 "data" 數(shù)組
if (j.contains("data") && j["data"].is_array()) {
// 獲取data數(shù)組
json dataArray = j["data"];
// 遍歷數(shù)組中的每個元素
for (const auto& item : dataArray) {
// 檢查元素是否包含name和age字段且類型正確
if (item.contains("name") && item["name"].is_string() && item.contains("age") && item["age"].is_number()) {
// 提取name和age字段的值
std::string name = item["name"];
int age = item["age"];
// 在日志中顯示name和age信息
wxLogMessage(wxString::FromUTF8("Name: %s, Age: %d"), wxString::FromUTF8(name.c_str()), age);
}
}
} else {
// 如果缺少data數(shù)組或格式不正確,記錄錯誤日志
wxLogInfo(wxString::FromUTF8("JSON格式錯誤: 缺少data數(shù)組或格式不正確"));
}
} catch (const json::parse_error& e) {
// JSON 解析失敗
std::string parseErrorMsg = "JSON解析失敗: " + std::string(e.what());
wxLogError(wxString::FromUTF8(parseErrorMsg.c_str()));
}
}
3.2.2 FormatJsonForHtml方法實現(xiàn)
// 格式化JSON字符串用于HTML顯示
wxString JsonHandler::FormatJsonForHtml(const wxString& jsonStr, const bool& formatBit) {
try {
// 確保使用UTF-8編碼
std::string utf8Json = std::string(jsonStr.ToUTF8());
// 使用nlohmann庫解析JSON字符串
json j = json::parse(utf8Json);
wxLogError("***************************************************");
wxLogError(j.dump());
wxLogError("***************************************************");
// 遞歸生成帶有HTML類名的JSON字符串
wxString formattedJson;
if (!formatBit) {
// 使用不帶縮進的方式格式化JSON
formattedJson = FormatJsonValue(j);
} else {
// 使用帶縮進的方式格式化JSON
formattedJson = FormatJsonValueFormat(j, 0);
}
wxLogError(wxT("格式化JSON字符串成功!"));
// 返回格式化后的JSON字符串
return formattedJson;
} catch (const json::parse_error& e) {
// 記錄JSON解析錯誤日志
wxLogError("JSON Parse Err: %s", e.what());
wxLogError(wxT("格式化JSON字符串失??!"));
// 返回原始JSON字符串
return jsonStr;
}
}
3.2.3 FormatJsonValue方法實現(xiàn)
// 遞歸生成帶有HTML類名的JSON字符串(不帶格式化)
wxString JsonHandler::FormatJsonValue(const json& j) {
// 判斷JSON值是否為對象類型
if (j.is_object()) {
// 如果是 JSON 對象
wxString result = wxT("{");
bool first = true;
// 遍歷對象中的每個鍵值對
for (auto& [key, value] : j.items()) {
if (!first) {
// 如果不是第一個元素,添加逗號分隔符
result += wxT(",");
}
first = false;
// 添加鍵,使用特定CSS類名進行標(biāo)記
result += wxString::Format(wxT("<span class='json-key'>\"%s\"</span>: "), wxString::FromUTF8(key.c_str()));
// 遞歸處理值
result += FormatJsonValue(value);
}
result += wxT("}");
wxLogError("----------------------------------------------------------------------");
wxLogError(result);
wxLogError("----------------------------------------------------------------------");
// 返回格式化后的對象字符串
return result;
} else if (j.is_array()) {
// 如果是 JSON 數(shù)組
wxString result = wxT("[");
bool first = true;
// 遍歷數(shù)組中的每個元素
for (auto& item : j) {
if (!first) {
// 如果不是第一個元素,添加逗號分隔符
result += wxT(",");
}
first = false;
// 遞歸處理數(shù)組項
result += FormatJsonValue(item);
}
result += wxT("]");
// 返回格式化后的數(shù)組字符串
return result;
} else if (j.is_string()) {
// 如果是 JSON 字符串
std::string jsonString = j.get<std::string>();
// 使用 wxString::FromUTF8 正確處理UTF-8編碼的字符串
wxString wxStringValue = wxString::FromUTF8(jsonString.c_str());
wxLogMessage("字符串值: %s", wxStringValue);
// 轉(zhuǎn)義HTML特殊字符以防止在HTML中顯示錯誤
wxString escapedValue = wxStringValue;
escapedValue.Replace("&", "&"); // 轉(zhuǎn)義&符號
escapedValue.Replace("<", "<"); // 轉(zhuǎn)義<符號
escapedValue.Replace(">", ">"); // 轉(zhuǎn)義>符號
escapedValue.Replace("\"", """); // 轉(zhuǎn)義雙引號
escapedValue.Replace("'", "'"); // 轉(zhuǎn)義單引號
// 使用特定CSS類名標(biāo)記字符串值并返回
return wxString::Format("<span class='json-string'>\"%s\"</span>", escapedValue);
} else if (j.is_number_integer() || j.is_number_unsigned()) {
// 如果是 JSON 數(shù)字(整數(shù))
// 使用特定CSS類名標(biāo)記整數(shù)并返回
return wxString::Format(wxT("<span class='json-number'>%lld</span>"), j.get<int64_t>());
} else if (j.is_number_float()) {
// 如果是 JSON 數(shù)字(浮點數(shù))
// 使用特定CSS類名標(biāo)記浮點數(shù)并返回
return wxString::Format(wxT("<span class='json-number'>%.6f</span>"), j.get<double>());
} else if (j.is_boolean()) {
// 如果是 JSON 布爾值
// 根據(jù)布爾值返回true或false,并使用特定CSS類名標(biāo)記
return j.get<bool>() ? wxT("<span class='json-boolean'>true</span>") : wxT("<span class='json-boolean'>false</span>");
} else if (j.is_null()) {
// 如果是 JSON null
// 使用特定CSS類名標(biāo)記null值并返回
return wxT("<span class='json-null'>null</span>");
}
// 對于其他類型,使用特定CSS類名標(biāo)記并返回
return wxString::Format("<span class='json-string'>%s</span>", j.dump().c_str());
}
3.2.4 FormatJsonValueFormat方法實現(xiàn)
// 遞歸生成帶有HTML類名的JSON字符串(帶格式化和縮進)
wxString JsonHandler::FormatJsonValueFormat(const json& j, int indentLevel) {
// 生成當(dāng)前層級的縮進字符串(每級2個空格)
wxString indent(indentLevel * 2, ' ');
// 生成內(nèi)層縮進字符串(比當(dāng)前層級多一級)
wxString indentInner((indentLevel + 1) * 2, ' ');
// 判斷JSON值是否為對象類型
if (j.is_object()) {
// 如果是 JSON 對象
if (j.empty()) {
// 如果對象為空,直接返回{}
return wxT("{}");
}
wxString result = wxT("{\n");
bool first = true;
// 遍歷對象中的每個鍵值對
for (auto& [key, value] : j.items()) {
if (!first) {
// 如果不是第一個元素,添加逗號和換行符
result += wxT(",\n");
}
first = false;
// 添加鍵和值,帶縮進
result += indentInner + wxString::Format(
wxT("<span class='json-key'>\"%s\"</span>: %s"),
wxString::FromUTF8(key.c_str()),
// 遞歸處理值,縮進層級加1
FormatJsonValueFormat(value, indentLevel + 1)
);
}
// 添加換行符、縮進和結(jié)束括號
result += wxT("\n") + indent + wxT("}");
// 返回格式化后的對象字符串
return result;
} else if (j.is_array()) {
// 如果是 JSON 數(shù)組
if (j.empty()) {
// 如果數(shù)組為空,直接返回[]
return wxT("[]");
}
wxString result = wxT("[\n");
bool first = true;
// 遍歷數(shù)組中的每個元素
for (auto& item : j) {
if (!first) {
// 如果不是第一個元素,添加逗號和換行符
result += wxT(",\n");
}
first = false;
// 添加數(shù)組項,帶縮進
result += indentInner + FormatJsonValueFormat(item, indentLevel + 1);
}
// 添加換行符、縮進和結(jié)束括號
result += wxT("\n") + indent + wxT("]");
// 返回格式化后的數(shù)組字符串
return result;
} else if (j.is_string()) {
// 如果是 JSON 字符串
std::string jsonString = j.get<std::string>();
// 使用 wxString::FromUTF8 正確處理UTF-8編碼的字符串
wxString wxStringValue = wxString::FromUTF8(jsonString.c_str());
wxLogMessage("字符串值: %s", wxStringValue);
// 轉(zhuǎn)義HTML特殊字符以防止在HTML中顯示錯誤
wxString escapedValue = wxStringValue;
escapedValue.Replace("&", "&"); // 轉(zhuǎn)義&符號
escapedValue.Replace("<", "<"); // 轉(zhuǎn)義<符號
escapedValue.Replace(">", ">"); // 轉(zhuǎn)義>符號
escapedValue.Replace("\"", """); // 轉(zhuǎn)義雙引號
escapedValue.Replace("'", "'"); // 轉(zhuǎn)義單引號
// 使用特定CSS類名標(biāo)記字符串值并返回
return wxString::Format("<span class='json-string'>\"%s\"</span>", escapedValue);
} else if (j.is_number_integer() || j.is_number_unsigned()) {
// 如果是 JSON 數(shù)字(整數(shù))
// 使用特定CSS類名標(biāo)記整數(shù)并返回
return wxString::Format(wxT("<span class='json-number'>%lld</span>"), j.get<int64_t>());
} else if (j.is_number_float()) {
// 如果是 JSON 數(shù)字(浮點數(shù))
// 使用特定CSS類名標(biāo)記浮點數(shù)并返回
return wxString::Format(wxT("<span class='json-number'>%.6f</span>"), j.get<double>());
} else if (j.is_boolean()) {
// 如果是 JSON 布爾值
// 根據(jù)布爾值返回true或false,并使用特定CSS類名標(biāo)記
return j.get<bool>() ? wxT("<span class='json-boolean'>true</span>") : wxT("<span class='json-boolean'>false</span>");
} else if (j.is_null()) {
// 如果是 JSON null
// 使用特定CSS類名標(biāo)記null值并返回
return wxT("<span class='json-null'>null</span>");
}
// 對于其他類型,使用特定CSS類名標(biāo)記并返回
return wxString::Format("<span class='json-string'>%s</span>", j.dump().c_str());
}
3.2.5 GenerateJsonHtml方法實現(xiàn)
// 生成 HTML 頁面
wxString JsonHandler::GenerateJsonHtml(const wxString& jsonResponse, const bool& formatBit) {
wxLogError("jsonResponse:---------------------------------------");
wxLogError(jsonResponse);
wxLogError("jsonResponse:---------------------------------------");
// 格式化JSON數(shù)據(jù)
wxString formattedJson = FormatJsonForHtml(jsonResponse, formatBit);
// 構(gòu)造完整的 HTML 字符串
wxString html = wxString::Format(
R"(<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8'>
<title>JSON響應(yīng)</title>
<style>
body {
font-family: 'Segoe UI', Arial, sans-serif;
background-color: #f5f5f5;
margin: 0;
padding: 20px;
}
.json-container {
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 20px;
overflow-x: auto;
}
h1 {
color: #333;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
margin-top: 0;
}
pre {
font-family: 'Consolas', 'Courier New', monospace;
font-size: 14px;
line-height: 1.4;
margin: 0;
white-space: pre-wrap; /* 保留空格和換行 */
}
.json-key { color: #e74c3c; font-weight: bold; }
.json-string { color: #27ae60; }
.json-number { color: #3498db; font-weight: bold; }
.json-boolean { color: #9b59b6; font-weight: bold; }
.json-null { color: #95a5a6; font-weight: bold; }
.toggle { cursor: pointer; }
</style>
<script src="./static/highlight.min.js"></script>
<link rel="stylesheet" href="./static/default.min.css" rel="external nofollow" >
<script>
document.addEventListener('DOMContentLoaded', function() {
hljs.highlightAll();
const toggles = document.querySelectorAll('.toggle');
toggles.forEach(toggle => {
toggle.addEventListener('click', function() {
const content = this.nextElementSibling;
if (content.style.display === 'none') {
content.style.display = 'block';
} else {
content.style.display = 'none';
}
});
});
});
</script>
</head>
<body>
<h1>服務(wù)器響應(yīng)</h1>
<div class='json-container'><pre>%s</pre></div>
</body>
</html>)",
formattedJson
);
// 日志輸出,用于調(diào)試
wxLogInfo(wxString::FromUTF8("生成的完整HTML:\n%s"), html);
// 返回生成的HTML頁面
return html;
}
4. MyFrame.cpp調(diào)用JsonHandler中封裝的各個方法示例
在主框架類MyFrame中,我們通過jsonHandler實例調(diào)用JsonHandler類中封裝的方法。
4.1 示例1:處理GET請求返回的JSON數(shù)據(jù)
// 獲取文件列表的事件處理函數(shù)
void MyFrame::OnGetFileLists(wxCommandEvent& event) {
// 發(fā)送GET請求獲取文件列表
std::string url = "/files";
std::string response = httpClient.HttpGet(url);
// 檢查響應(yīng)是否為空
if (response.empty()) {
// 如果返回的響應(yīng)為空,可能是請求失敗
wxLogError("GET request failed or returned empty response.");
m_textCtrl->SetValue("GET Request Failed: Empty response.");
return;
}
// 保存原始JSON數(shù)據(jù)供后續(xù)使用
jsonHandler.SetRawJsonData(wxString::FromUTF8(response.c_str()));
// 在瀏覽器控件中顯示格式化的JSON數(shù)據(jù)
wxString html = jsonHandler.GenerateJsonHtml(wxString::FromUTF8(response.c_str()), false);
m_webView->SetPage(html, "UTF-8");
// 解析JSON數(shù)據(jù)并填充下拉框
try {
// 使用nlohmann庫解析JSON字符串
json j = json::parse(response);
// 清空下拉框中的現(xiàn)有內(nèi)容
m_comboBox->Clear();
// 檢查是否存在 "data" 對象以及 "data.filelist" 數(shù)組
if (j.contains("data") && j["data"].is_object()) {
// 獲取data對象
json dataObj = j["data"];
// 檢查是否存在 "filelist" 數(shù)組
if (dataObj.contains("filelist") && dataObj["filelist"].is_array()) {
// 獲取文件列表數(shù)組
json fileArray = dataObj["filelist"];
// 遍歷數(shù)組中的每個文件項
for (const auto& item : fileArray) {
// 檢查項是否包含name字段且為字符串類型
if (item.contains("name") && item["name"].is_string()) {
// 提取文件名
std::string name = item["name"];
// 將文件名添加到下拉框中
m_comboBox->Append(wxString::FromUTF8(name.c_str()));
}
}
}
}
}
// 捕獲JSON解析錯誤
catch (const json::parse_error& e) {
// JSON 解析失敗
std::string parseErrorMsg = "JSON解析失敗: " + std::string(e.what());
wxLogError(wxString::FromUTF8(parseErrorMsg.c_str()));
}
}
4.2 示例2:格式化顯示JSON數(shù)據(jù)
// 格式化JSON顯示的事件處理函數(shù)
void MyFrame::OnFormatJson(wxCommandEvent& event) {
// 使用格式化方式生成JSON HTML頁面
wxString html = jsonHandler.GenerateJsonHtml(jsonHandler.GetRawJsonData(), true);
// 清除WebView的歷史記錄
m_webView->ClearHistory();
// 重新加載頁面
m_webView->Reload();
// 在WebView中顯示格式化的JSON數(shù)據(jù)
m_webView->SetPage(html, "UTF-8");
}
5. 總結(jié)
通過使用nlohmann/json庫和封裝的JsonHandler類,我們能夠:
- 簡化JSON數(shù)據(jù)的解析和處理過程
- 提供格式化的JSON數(shù)據(jù)顯示功能
- 實現(xiàn)JSON數(shù)據(jù)的保存和重用
- 保證代碼的模塊化和可維護性
nlohmann/json庫的使用大大簡化了C++中JSON數(shù)據(jù)的處理,其直觀的API設(shè)計使得JSON操作就像訪問原生數(shù)據(jù)結(jié)構(gòu)一樣簡單。通過封裝在JsonHandler類中,我們實現(xiàn)了代碼的重用和更好的維護性。
以上就是C++使用nlohmann/json庫解析和處理JSON數(shù)據(jù)的操作指南的詳細(xì)內(nèi)容,更多關(guān)于C++ nlohmann/json解析和處理JSON的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++求1到n中1出現(xiàn)的次數(shù)以及數(shù)的二進制表示中1的個數(shù)
這篇文章主要介紹了C++求1到n中1出現(xiàn)的次數(shù)以及數(shù)的二進制表示中1的個數(shù),兩道基礎(chǔ)的算法題目,文中也給出了解題思路,需要的朋友可以參考下2016-02-02
Qt?QGraphicsItem?移動時出現(xiàn)殘影問題記錄
自定義QGraphicsItem時,繪制rect,對象移動時出現(xiàn)殘影的問題記錄,本文給大家介紹Qt?QGraphicsItem?移動時出現(xiàn)殘影問題記錄,感興趣的朋友跟隨小編一起看看吧2024-06-06
淺談C++中thread庫join和detach的區(qū)別
這篇文章主要為大家介紹了C++中thread庫join和detach的區(qū)別,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2021-11-11

