C語(yǔ)言實(shí)現(xiàn)手寫(xiě)JSON解析的方法詳解
什么是JSON
JSON(JavaScript Object Notation)是一種輕量級(jí)的數(shù)據(jù)交換格式,用來(lái)傳輸屬性值或者序列性的值組成的數(shù)據(jù)對(duì)象。
JSON是JavaScript的一個(gè)子集。
具有良好的可讀性和便于快速編寫(xiě)的特性。
JSON是獨(dú)立于語(yǔ)言的文本格式,并且采用了類(lèi)似C語(yǔ)言家族的一些習(xí)慣。
JSON數(shù)據(jù)格式與語(yǔ)言無(wú)關(guān),是目前網(wǎng)絡(luò)中主流的數(shù)據(jù)傳輸格式之一,使用率幾乎為99%。
JSON支持的數(shù)據(jù)類(lèi)型
JSON里面的數(shù)據(jù)以一種鍵值對(duì)的方式存在,即“key”:“value” 類(lèi)型可以是數(shù)據(jù)類(lèi)型中的任意一種:
JSON語(yǔ)法規(guī)則
JSON的語(yǔ)法規(guī)則非常簡(jiǎn)單,使用
大括號(hào)——{}
中括號(hào)——[]
逗號(hào)——,
冒號(hào)——:
雙引號(hào)——“” (一般可以不需要)
JSON的解析
在解析JSON是我們會(huì)遇到兩種情況,其一是解析大括號(hào)——{}類(lèi)型,其二是解析中括號(hào)類(lèi)型——[],以及這兩種類(lèi)型的組合模式。
JSON基本語(yǔ)法
對(duì)象類(lèi)型(Object)
{ "name" : "佩奇" , "age" : "8" }
數(shù)組類(lèi)型(Array)
[ "喜羊羊","懶羊羊",5,true,null ]
對(duì)象組合形
{ "name" : "佩奇" , "age" : "8", "friend" :[{"name" : " 喜羊羊 " , "age" : "5"} , {"name" : " 懶羊羊 " , "age" : "6"}] //對(duì)象類(lèi)型嵌套數(shù)組類(lèi)型,數(shù)組類(lèi)型嵌套對(duì)象類(lèi)型 }
數(shù)組組合型
[ [{"name" : "佩奇" ,"age" : "8"},{"name" : "佩奇" ,"age" : "8"}],[{},{}]]
編寫(xiě)解析器
頭文件
// // Created by huanmin on 2022/9/15. // #ifndef STUDY_JSON_H #define STUDY_JSON_H #include "../util/str_util.h" #include <stdio.h> #include "charhashmap.h" #include "charlist.h" #include "../util/assertmy.h" static char *str_to_json_placeholder(char *string, CharHashMap *map, CharHashMap *list); static char *querySubstitute(char *string, CharHashMap *map, CharHashMap *list); BOOL str_is_json(char *string); CharList *str_to_json_array(char *array); CharHashMap *str_to_json_map(char *dict); char *map_to_json_str(CharHashMap *pMap); char *array_to_json_str(CharList *pCharlist); BOOL str_is_map(char *str); BOOL str_is_array(char *str); #endif //STUDY_JSON_H
實(shí)現(xiàn)文件
// // Created by huanmin on 2022/9/15. // #include "json.h" //轉(zhuǎn)換字符串為JSON_先進(jìn)行占位符替換 static char *str_to_json_placeholder(char *string, CharHashMap *map, CharHashMap *list) { //判斷是否有[],如果有那么提取出來(lái),并且將位置上的內(nèi)容替換為 @arri int zi = 0; int start = -1; while ((start = str_find(string, "[")) != -1) { int length = str_length(string); int jilu = 0; int end = -1; for (int i = start; i < length; ++i) { if (string[i] == '[') { jilu++; } if (string[i] == ']') { jilu--; if (jilu == 0) { end = i; break; } } } char *arr_str = str_substring(string, start, end); char *append = str_concat(3, "@arr", int_to_str(zi), "@"); putCharHashMap(list, append, arr_str); string = str_replace(string, arr_str, append); zi++; } zi = 0; start = -1; //判斷是否有{},如果有那么提取出來(lái), 并且將位置上的內(nèi)容替換為@mapi while ((start = str_find(string, "{")) != -1) { int length = str_length(string); int jilu = 0; int end = -1; for (int i = start; i < length; ++i) { if (string[i] == '{') { jilu++; } if (string[i] == '}') { jilu--; if (jilu == 0) { end = i; break; } } } char *map_str = str_substring(string, start, end); char *append = str_concat(3, "@map", int_to_str(zi), "@"); putCharHashMap(map, append, map_str); string = str_replace(string, map_str, append); zi++; } return string; } static char *querySubstitute(char *string, CharHashMap *map, CharHashMap *list) { char *str = string; int start = -1; //替換 if (str_start_with(string, "@map")) { while ((start = str_find(str, "@map")) != -1) { int end = str_find_n(str, "@", start + 1, str_length(str)); char *substring = str_substring(str, start, end); str = (char *) getCharHashMap(map, substring); } } else if (str_start_with(string, "@arr")) { //替換參數(shù)為原來(lái)的值 while ((start = str_find(str, "@arr")) != -1) { int end = str_find_n(str, "@", start + 1, str_length(str)); char *substring = str_substring(str, start, end); str = (char *) getCharHashMap(list, substring); } } start = -1; //判斷是否還包含@map或者@arr,如果有那么就繼續(xù)替換 while ((start = str_find(str, "@map")) != -1 || (start = str_find(str, "@arr")) != -1) { //截取所有的@map@和@arr@,并且將其替換為原來(lái)的字符串 CharList *pCharlist = createCharList(10); while ((str_find_n(str, "@map", start, str_length(str))) != -1 || (str_find_n(str, "@arr", start, str_length(str))) != -1) { int end = str_find_n(str, "@", start + 1, str_length(str)); char *substring = str_substring(str, start, end); addCharList(pCharlist, substring); start = end; } CharListIterator *pIterator = createCharListIterator(pCharlist); while (hasNextCharListIterator(pIterator)) { char *key = nextCharListIterator(pIterator); if (str_start_with(key, "@map")) { char *value = (char *) getCharHashMap(map, key); str = str_replace(str, key, value); } else if (str_start_with(key, "@arr")) { char *value = (char *) getCharHashMap(list, key); str = str_replace(str, key, value); } } } return str; } //將字符串?dāng)?shù)組格式[1,2,3]或者[{a:b,c:d},{a:b,c:d}]轉(zhuǎn)換為L(zhǎng)ist ,(沒(méi)有任何格式驗(yàn)證,全靠自己規(guī)范編寫(xiě)) CharList *str_to_json_array(char *array) { if (array == NULL || str_length(array) == 0) { return NULL; } char *trim = str_trim(array); char *string = str_substring(trim, 1, str_length(trim) - 2); CharHashMap *map = createCharHashMap(10); CharHashMap *list = createCharHashMap(10); char *string1 = str_to_json_placeholder(string, map, list); CharList *pCharlist = str_split(string1, ","); for (int i = 0; i < pCharlist->len; ++i) { char *v = pCharlist->str[i]; pCharlist->str[i] = querySubstitute(v, map, list); } return pCharlist; } //將json對(duì)象字符串{a:b,c:d},轉(zhuǎn)換為hashMap ,(沒(méi)有任何格式驗(yàn)證,全靠自己規(guī)范編寫(xiě)) CharHashMap *str_to_json_map(char *dict) { if (dict == NULL || str_length(dict) == 0) { return NULL; } char *trim = str_trim(dict); char *string = str_substring(trim, 1, str_length(trim) - 2); CharHashMap *map = createCharHashMap(10); CharHashMap *list = createCharHashMap(10); char *string1 = str_to_json_placeholder(string, map, list); CharList *pCharlist = str_split(string1, ","); int str_len = pCharlist->len; if (str_len == 0) { return NULL; } //分割key和value CharHashMap *pMap = createCharHashMap(str_len); for (int i = 0; i < str_len; i++) { char *str = pCharlist->str[i]; CharList *pList = str_split(str, ":"); char *key = str_trim(pList->str[0]); char *value = str_trim(pList->str[1]); putCharHashMap(pMap, key, querySubstitute(value, map, list)); } return pMap; } //將hashMap轉(zhuǎn)換為json對(duì)象{a:b,c:d,v:[1,2],f:{a:b,c:d}} ,(沒(méi)有任何格式驗(yàn)證,全靠自己規(guī)范編寫(xiě)) char *map_to_json_str(CharHashMap *pMap) { if (pMap == NULL) { return NULL; } char *string = str_create("{"); int len = pMap->size; //創(chuàng)建迭代器 CharHashMapIterator *pIterator = createCharHashMapIterator(pMap); while (hasNextCharHashMapIterator(pIterator)) { CharKvLinkedNode *pNode = nextCharHashMapIterator(pIterator); string = str_append(string, pNode->key); string = str_append(string, ":"); string = str_append(string, pNode->value); if (len != 1) { string = str_append(string, ","); } len--; } string = str_append(string, "}"); return string; } //將CharList轉(zhuǎn)換為json數(shù)組格式[1,2,[1,2,3]]或者[{},{}] ,(沒(méi)有任何格式驗(yàn)證,全靠自己規(guī)范編寫(xiě)) char *array_to_json_str(CharList *pCharlist) { if (pCharlist == NULL) { return NULL; } char *string = str_create("["); for (int i = 0; i < pCharlist->len; ++i) { string = str_append(string, pCharlist->str[i]); if (i != pCharlist->len - 1) { string = str_append(string, ","); } } string = str_append(string, "]"); return string; } //判斷是否是json對(duì)象 BOOL str_is_map(char *str) { if (str == NULL) { return FALSE; } if (str_length(str) < 2) { return FALSE; } if (str_start_with(str, "{") && str_end_with(str, "}")) { return TRUE; } return FALSE; } //判斷是否是數(shù)組 BOOL str_is_array(char *str) { if (str == NULL) { return FALSE; } if (str_length(str) < 2) { return FALSE; } if (str_start_with(str, "[") && str_end_with(str, "]")) { return TRUE; } return FALSE; }
到此這篇關(guān)于C語(yǔ)言實(shí)現(xiàn)手寫(xiě)JSON解析的方法詳解的文章就介紹到這了,更多相關(guān)C語(yǔ)言 JSON解析內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談C++為什么非要引入那幾種類(lèi)型轉(zhuǎn)換
這篇文章主要介紹了C++為什么非要引入那幾種類(lèi)型轉(zhuǎn)換,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03C語(yǔ)言指針之必須要掌握的指針基礎(chǔ)知識(shí)
這篇文章主要介紹了C語(yǔ)言指針必須要掌握的基礎(chǔ)知識(shí),文中實(shí)例講解的很清晰,有不太懂的同學(xué)可以研究下,希望能夠給你帶來(lái)幫助2021-09-09詳解C語(yǔ)言如何執(zhí)行HTTP GET請(qǐng)求
在現(xiàn)代互聯(lián)網(wǎng)時(shí)代,網(wǎng)絡(luò)數(shù)據(jù)的獲取和分析變得越來(lái)越重要,本文我們將使用C語(yǔ)言和libcurl庫(kù)來(lái)編寫(xiě)一個(gè)簡(jiǎn)單的網(wǎng)絡(luò)爬蟲(chóng),以執(zhí)行HTTP GET請(qǐng)求并獲取淘寶網(wǎng)頁(yè)的內(nèi)容,感興趣的可以了解下2023-11-11詳解C/C++中const關(guān)鍵字的用法及其與宏常量的比較
簡(jiǎn)單的說(shuō)const關(guān)鍵字修飾的變量具有常屬性,也就是說(shuō)它所修飾的變量不能被修改,下文給大家介紹C/C++中const關(guān)鍵字的用法及其與宏常量的比較,需要的朋友可以參考下2017-07-07mfc入門(mén)教程之實(shí)現(xiàn)一個(gè)簡(jiǎn)單的計(jì)算器
這篇文章主要介紹了mfc入門(mén)教程,手把手教你如何開(kāi)發(fā)一個(gè)簡(jiǎn)單的計(jì)算器,需要的朋友可以參考下2019-04-04C++語(yǔ)言const 關(guān)鍵字使用方法圖文詳解
在類(lèi)中,如果你不希望某些數(shù)據(jù)被修改,可以使用const關(guān)鍵字加以限定。const 可以用來(lái)修飾成員變量、成員函數(shù)以及對(duì)象2020-01-01