C++ Builder 解析 json赢乓,Json::CharReaderBuilder 的使用方法

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 編譯器的對鉤去掉:

選擇 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 的運(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": a1234.56 解析錯(cuò)誤,沒有拋出異常

"value": "1234.56" 讀取為 double 時(shí)拋出異常摩幔,分析原因彤委,解析 json 時(shí)認(rèn)為這是一個(gè)字符串值,解析 json 通過或衡,但是讀取時(shí)焦影,由于這是字符串值,讀成 double 時(shí)類型錯(cuò)誤封断,拋出異常偷办。

"value": "1234.56" 讀取為 double 時(shí)拋出異常

五. 判斷 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)目文件,編譯好了的庫文件狱意、例子程序等湖苞。


參考:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末财骨,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子藏姐,更是在濱河造成了極大的恐慌隆箩,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件羔杨,死亡現(xiàn)場離奇詭異捌臊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)兜材,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門理澎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人曙寡,你說我怎么就攤上這事糠爬。” “怎么了举庶?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵执隧,是天一觀的道長。 經(jīng)常有香客問我,道長殴玛,這世上最難降的妖魔是什么捅膘? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮滚粟,結(jié)果婚禮上寻仗,老公的妹妹穿的比我還像新娘。我一直安慰自己凡壤,他們只是感情好署尤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著亚侠,像睡著了一般曹体。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上硝烂,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天箕别,我揣著相機(jī)與錄音,去河邊找鬼滞谢。 笑死串稀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的狮杨。 我是一名探鬼主播母截,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼橄教!你這毒婦竟也來了清寇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤护蝶,失蹤者是張志新(化名)和其女友劉穎华烟,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體滓走,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡垦江,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了搅方。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡绽族,死狀恐怖姨涡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吧慢,我是刑警寧澤涛漂,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響匈仗,放射性物質(zhì)發(fā)生泄漏瓢剿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一悠轩、第九天 我趴在偏房一處隱蔽的房頂上張望间狂。 院中可真熱鬧,春花似錦火架、人聲如沸鉴象。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纺弊。三九已至,卻和暖如春骡男,著一層夾襖步出監(jiān)牢的瞬間淆游,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工隔盛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留稽犁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓骚亿,卻偏偏與公主長得像已亥,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子来屠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容