jsoncpp 最新版本為 master 分支妹萨,必須用新版本的支持 C++ 11 的編譯器,C++ Builder 需要選擇 clang 編譯器标捺,不可以使用 Borland 編譯器懊纳。
下載和編譯 jsoncpp 可以參考《C++ Builder 編譯 jsoncpp 庫 (master 分支)》
- 使用 jsoncpp 靜態(tài)庫
- 解析 json 字符串
- 解析 json 文件
- 可能拋出的異常
- 判斷 Json::Value 的類型
- 下載本文例子
一. 使用 jsoncpp 靜態(tài)庫
1. 下載和編譯 jsoncpp 靜態(tài)庫
下載和編譯 jsoncpp 可以參考《C++ Builder 編譯 jsoncpp 庫 (master 分支)》
2. 在項(xiàng)目選項(xiàng)里面揉抵,添加頭文件和庫文件的路徑
選擇菜單 Project -> Options
頭文件的路徑需要添加這個(gè)文件夾:
庫文件的路徑需要添加這個(gè)文件夾:
選擇 clang 編譯器,把 Borland 編譯器的對鉤去掉:
3. 包含頭文件和鏈接庫文件
#include "json/json.h"
#if defined(__clang__) && (__POINTER_WIDTH__ == 64)
#pragma link "jsoncpp.a"
#else
#pragma link "jsoncpp.lib"
#endif
二. 解析 json 字符串
使用 Json::CharReaderBuilder 和 Json::CharReader 解析 json 字符串,解析之后放在 Json::Value 里面茂缚。
Json::Value 里面存儲的可能是一個(gè)單個(gè)的值戏罢,比如整數(shù)、浮點(diǎn)數(shù)脚囊、字符串等龟糕,也可能是一組鍵值對,也可能是數(shù)組悔耘。
Json::Value v;
如果 v 是 "key" : value 形式的鍵值對讲岁,
Json::Value &value = v["key"]; // 關(guān)鍵字 key 的值
如果 v 是數(shù)組
Json::Value &value = v[i]; // 數(shù)組第 i 個(gè)元素的值
如果要把 Json::Value 儲存的單個(gè)值讀出來,需要用 Json::Value 的成員函數(shù):
函數(shù) | 得到的值 |
---|---|
asBool() | 布爾型 bool |
asInt() | 整型 int |
asInt64() | 64位整型 long long |
asUInt() | 無符號整型 unsigned int |
asUInt64() | 64位無符號整型 unsigned long long |
asLargestInt() | 最大位數(shù)的整型 intmax_t |
asLargestUInt() | 最大位數(shù)的無符號整型 uintmax_t |
asFloat() | 浮點(diǎn)數(shù) float |
asDouble() | 雙精度浮點(diǎn)數(shù) double |
asString() | 字符串 std::string |
asCString() | 字符串 const char * |
例:從 Memo 控件里面獲取 json 字符串衬以,假定內(nèi)容如下:
{
"name" : "JSON 測試程序 - 玄坴",
"desc" : "Test JSON, Copyright ? Hsuanlu",
"value": 1234.56,
"故障" :
[
{ "編碼":101, "描述":"故障1" },
{ "編碼":102, "描述":"故障2" }
]
}
程序代碼:
雖然 C++ 11 規(guī)定了 u8"這是 UTF-8 字符串"
這樣的寫法缓艳,但是目前的 C++ Builder 編譯器還不支持,所以定義了一個(gè) _u8s
在程序里面使用能夠簡單方便一些:
#define _u8s(s) UTF8String(s).c_str()
#define _u8s(s) UTF8String(s).c_str()
void __fastcall TForm1::Button1Click(TObject *Sender)
{
try
{
UTF8String txt = Memo1->Text;
Json::Value jsValue;
Json::String jsErrors;
Json::CharReaderBuilder jcrBuilder;
std::unique_ptr<Json::CharReader>jcReader(jcrBuilder.newCharReader());
if(!jcReader->parse(txt.c_str(), txt.c_str()+txt.Length(), &jsValue, &jsErrors))
{
Memo2->Lines->Add(L"JSON 解析錯(cuò)誤");
return;
}
UTF8String sVal;
double lfVal;
int iVal;
sVal = jsValue["name"].asCString();
Memo2->Lines->Add(sVal);
sVal = jsValue["desc"].asCString();
Memo2->Lines->Add(sVal);
lfVal = jsValue["value"].asDouble();
Memo2->Lines->Add(lfVal);
for(int i=0; i<2; i++)
{
Json::Value &jsFault = jsValue[_u8s(L"故障")][i];
iVal = jsFault[_u8s(L"編碼")].asInt();
Memo2->Lines->Add(iVal);
sVal = jsFault[_u8s(L"描述")].asCString();
Memo2->Lines->Add(sVal);
}
}
catch(std::exception &e)
{
UTF8String sErrStr = e.what();
Memo2->Lines->Add(L"錯(cuò)誤:" + sErrStr);
}
catch(Exception &e)
{
UTF8String sErrStr = e.Message;
Memo2->Lines->Add(L"錯(cuò)誤:" + sErrStr);
}
}
運(yùn)行結(jié)果:
三. 解析 json 文件
只要把文件內(nèi)容讀到 UTF8String 里面就可以用前面的解析 json 字符串的方法解析了看峻。
下面程序把 L"d:\\folder\\filename.txt"
讀到 UTF8String txt
里面阶淘,按照 BOM 自動識別文件編碼 UTF-8 / UNICODE 等,如果沒有 BOM 會認(rèn)為是 ANSI 編碼 (由操作系統(tǒng)確定具體編碼备籽,Windows 10 新版在控制面板里面可以設(shè)為沒有 BOM 認(rèn)為是 UTF-8舶治,否則認(rèn)為是 ANSI)分井。
std::auto_ptr<TStringList>sl(new TStringList);
sl->LoadFromFile(L"d:\\folder\\filename.txt");
UTF8String txt = sl->Text;
如果要指定讀取的文件是 UTF-8 編碼车猬,LoadFromFile 需要加參數(shù) TEncoding::UTF8,如果讀取的文件不是 UTF-8 編碼尺锚,會拋出異常珠闰。
sl->LoadFromFile(L"d:\\folder\\filename.txt", TEncoding::UTF8);
文件讀取完成,就可以按照前面第二部分所述的解析 json 字符串的方法了瘫辩。
完整的例子:仍然需要前面例子的宏 #define _u8s(s) UTF8String(s).c_str()
void __fastcall TForm1::Button2Click(TObject *Sender)
{
try
{
std::auto_ptr<TStringList>sl(new TStringList);
sl->LoadFromFile(L"d:\\folder\\filename.txt");
UTF8String txt = sl->Text;
Json::Value jsValue;
Json::String jsErrors;
Json::CharReaderBuilder jcrBuilder;
std::unique_ptr<Json::CharReader>jcReader(jcrBuilder.newCharReader());
if(!jcReader->parse(txt.c_str(), txt.c_str()+txt.Length(), &jsValue, &jsErrors))
{
Memo2->Lines->Add(L"JSON 解析錯(cuò)誤");
return;
}
UTF8String sVal;
double lfVal;
int iVal;
sVal = jsValue["name"].asCString();
Memo2->Lines->Add(sVal);
sVal = jsValue["desc"].asCString();
Memo2->Lines->Add(sVal);
lfVal = jsValue["value"].asDouble();
Memo2->Lines->Add(lfVal);
for(int i=0; i<2; i++)
{
Json::Value &jsFault = jsValue[_u8s(L"故障")][i];
iVal = jsFault[_u8s(L"編碼")].asInt();
Memo2->Lines->Add(iVal);
sVal = jsFault[_u8s(L"描述")].asCString();
Memo2->Lines->Add(sVal);
}
}
catch(std::exception &e)
{
UTF8String sErrStr = e.what();
Memo2->Lines->Add(L"錯(cuò)誤:" + sErrStr);
}
catch(Exception &e)
{
UTF8String sErrStr = e.Message;
Memo2->Lines->Add(L"錯(cuò)誤:" + sErrStr);
}
}
四. 可能拋出的異常
必須要注意 jsoncpp 會拋出 std::exception 類型的異常伏嗜,而 C++ Builder 會拋出 Exception 類型的異常 (注意大小寫,這個(gè)的開頭字母是大寫的)伐厌,所以看到前面解析 json 字符串的例子捕獲了這兩種異常承绸。
例:前面解析字符串的例子,在 Memo1 里面輸入不合理的 json 內(nèi)容挣轨,測試一下程序運(yùn)行的結(jié)果:
"value": a1234.56
提示 json 解析錯(cuò)誤军熏,分析原因 a1234.56 不是數(shù)字,字符串需要有引號卷扮,在解析 json 的時(shí)候就出錯(cuò)了荡澎,沒有拋出異常均践。
"value": "1234.56" 讀取為 double 時(shí)拋出異常摩幔,分析原因彤委,解析 json 時(shí)認(rèn)為這是一個(gè)字符串值,解析 json 通過或衡,但是讀取時(shí)焦影,由于這是字符串值,讀成 double 時(shí)類型錯(cuò)誤封断,拋出異常偷办。
五. 判斷 Json::Value 的類型
在讀取 Json::Value 值的時(shí)候,如果類型錯(cuò)誤就會拋出異常澄港,所以在不確定類型的情況下椒涯,需要判斷類型。
Json::Value 的 type() 方法返回的是 Json::Value 的類型回梧。
類型枚舉值 | 說明 |
---|---|
nullValue | NULL 值 |
intValue | 有符號整數(shù) |
uintValue | 無符號整數(shù) |
realValue | 雙精度浮點(diǎn)數(shù) |
stringValue | UTF-8 字符串 |
booleanValue | 布爾值 |
arrayValue | 數(shù)組 |
objectValue | 一組 name/value 鍵值對 |
Json::Value 還有一些其他的判斷類型的方法:
判斷類型的方法 | 說明 |
---|---|
isNull() | 是 NULL 值 |
isBool() | 是布爾值 |
isNumeric() | 是數(shù)字 |
isIntegral() | 是整數(shù) |
isInt() | 是有符號整數(shù) |
isInt64() | 是 64 位有符號整數(shù) |
isUInt() | 是無符號整數(shù) |
isUInt64() | 是 64 位無符號整數(shù) |
isDouble() | 是浮點(diǎn)數(shù) |
isString() | 是字符串 |
isArray() | 是數(shù)組 |
isObject() | 是 name/value 鍵值對 |
六. 下載本文例子
請點(diǎn)擊:jsoncpp-master-1.9.3-src-cbuilder 下載 jsoncpp-master 1.9.3 源碼废岂、C++ Builder 項(xiàng)目文件,編譯好了的庫文件狱意、例子程序等湖苞。
參考: