C語言實現(xiàn)手寫JSON解析的方法詳解
什么是JSON
JSON(JavaScript Object Notation)是一種輕量級的數(shù)據(jù)交換格式,用來傳輸屬性值或者序列性的值組成的數(shù)據(jù)對象。
JSON是JavaScript的一個子集。
具有良好的可讀性和便于快速編寫的特性。
JSON是獨立于語言的文本格式,并且采用了類似C語言家族的一些習(xí)慣。
JSON數(shù)據(jù)格式與語言無關(guān),是目前網(wǎng)絡(luò)中主流的數(shù)據(jù)傳輸格式之一,使用率幾乎為99%。
JSON支持的數(shù)據(jù)類型
JSON里面的數(shù)據(jù)以一種鍵值對的方式存在,即“key”:“value” 類型可以是數(shù)據(jù)類型中的任意一種:
JSON語法規(guī)則
JSON的語法規(guī)則非常簡單,使用
大括號——{}
中括號——[]
逗號——,
冒號——:
雙引號——“” (一般可以不需要)
JSON的解析
在解析JSON是我們會遇到兩種情況,其一是解析大括號——{}類型,其二是解析中括號類型——[],以及這兩種類型的組合模式。
JSON基本語法
對象類型(Object)
{
"name" : "佩奇" ,
"age" : "8"
}
數(shù)組類型(Array)
[ "喜羊羊","懶羊羊",5,true,null ]
對象組合形
{
"name" : "佩奇" ,
"age" : "8",
"friend" :[{"name" : " 喜羊羊 " , "age" : "5"} , {"name" : " 懶羊羊 " , "age" : "6"}]
//對象類型嵌套數(shù)組類型,數(shù)組類型嵌套對象類型
}
數(shù)組組合型
[ [{"name" : "佩奇" ,"age" : "8"},{"name" : "佩奇" ,"age" : "8"}],[{},{}]]
編寫解析器
頭文件
// // 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
實現(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) {
//判斷是否有[],如果有那么提取出來,并且將位置上的內(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;
//判斷是否有{},如果有那么提取出來, 并且將位置上的內(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ù)為原來的值
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@,并且將其替換為原來的字符串
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)換為List ,(沒有任何格式驗證,全靠自己規(guī)范編寫)
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對象字符串{a:b,c:d},轉(zhuǎn)換為hashMap ,(沒有任何格式驗證,全靠自己規(guī)范編寫)
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對象{a:b,c:d,v:[1,2],f:{a:b,c:d}} ,(沒有任何格式驗證,全靠自己規(guī)范編寫)
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]]或者[{},{}] ,(沒有任何格式驗證,全靠自己規(guī)范編寫)
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對象
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語言實現(xiàn)手寫JSON解析的方法詳解的文章就介紹到這了,更多相關(guān)C語言 JSON解析內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解C/C++中const關(guān)鍵字的用法及其與宏常量的比較
簡單的說const關(guān)鍵字修飾的變量具有常屬性,也就是說它所修飾的變量不能被修改,下文給大家介紹C/C++中const關(guān)鍵字的用法及其與宏常量的比較,需要的朋友可以參考下2017-07-07

