柚子快報激活碼778899分享:一文搞懂JSON
柚子快報激活碼778899分享:一文搞懂JSON
目錄
什么是JSON?
JSON的基本數(shù)據(jù)類型
JSON的特點和優(yōu)勢(了解)
JSON格式規(guī)范(重點)
JSON的基本操作
關(guān)鍵接口的梳理
序列化
反序列化
答案和解析
序列化答案
反序列化答案
第一種思路
第二種思路
什么是JSON?
JSON(JavaScript Object Notation)是一種輕量級的數(shù)據(jù)交換格式,常用于將數(shù)據(jù)結(jié)構(gòu)化地傳輸和存儲。它由鍵值對組成,采用類似于JavaScript對象的格式來表示數(shù)據(jù)。JSON易于閱讀和編寫,并且易于解析和生成,成為廣泛應用于Web應用程序和數(shù)據(jù)交換的標準格式之一。
JSON的基本數(shù)據(jù)類型
類型 解釋 案例 字符 (String) 由雙引號包圍的Unicode字符序列 "Hello, World!" 數(shù)字(Number) 包括整數(shù)和浮點數(shù) 42,3.14 布爾值(Boolean) 表示真或假,C相關(guān)的實現(xiàn)庫可能會用0和1表示 值為true或false 空值 (Null) 表示空值 值為null 對象 (Object) 由一組無序的鍵值對組成,鍵是字符串,值可以是任意的JSON數(shù)據(jù)類型。鍵值對之間使用逗號分隔,整個對象使用花括號{}包圍 {"name": "John", "age": 30, "city": "New York"} 數(shù)組 (Array) 由一組有序的值組成,值可以是任意的JSON數(shù)據(jù)類型。值之間使用逗號分隔,整個數(shù)組使用方括號[]包圍 [1, 2, 3, 4, 5]
JSON的特點和優(yōu)勢(了解)
簡潔和易讀:JSON使用簡潔的文本格式表示數(shù)據(jù),易于閱讀和編寫。平臺無關(guān)性:JSON是一種獨立于編程語言和平臺的數(shù)據(jù)格式,可被多種編程語言解析和生成。易于解析和生成:JSON的解析和生成相對簡單,各種編程語言都提供了相應的JSON解析器和生成器。支持復雜數(shù)據(jù)結(jié)構(gòu):JSON支持嵌套、復雜的數(shù)據(jù)結(jié)構(gòu),可以表示對象、數(shù)組和各種組合類型的數(shù)據(jù)。與Web應用程序兼容性良好:JSON廣泛用于Web應用程序中,可以輕松地與JavaScript進行交互。
JSON格式規(guī)范(重點)
1. 數(shù)據(jù)使用鍵值對表示,鍵和值之間使用冒號(:)分隔。
例如:{"name": "John", "age": 30}
2. 鍵使用雙引號(")包圍,值可以是字符串、數(shù)字、布爾值、對象、數(shù)組或null。
例如:{"name": "John", "age": 30, "isStudent": true, "address": null}
3. 鍵值對之間使用逗號(,)分隔,最后一個鍵值對后不應有逗號。
例如:{"name": "John", "age": 30}
4. 字符串值使用雙引號(")包圍,可以包含任意Unicode字符序列,特殊字符可以使用轉(zhuǎn)義字符表示。
例如:"Hello, World!", "I "love" JSON"
5. 數(shù)字可以是整數(shù)或浮點數(shù),不使用引號包圍。
例如:42, 3.14
6. 布爾值只有兩個取值:true和false,不使用引號包圍。
例如:true, false
7. 數(shù)組使用方括號([])包圍,值之間使用逗號分隔。
例如:[1, 2, 3, 4, 5]
8. 對象使用花括號({})包圍,鍵值對之間使用逗號分隔。
例如:{"name": "John", "age": 30}
9. JSON是嚴格區(qū)分大小寫的,鍵和字符串值都應該使用雙引號包圍。
10. JSON可以嵌套,允許在對象中包含對象或數(shù)組,或在數(shù)組中包含對象或其他數(shù)組。
11. JSON不支持注釋,不允許在JSON數(shù)據(jù)中添加注釋。
下面是一個簡單的JSON
{
"name": "southernbrid",
"age": 14,
"gender": true,
"height": 1.65,
"grade": null,
"skills": [
"JavaScript",
"Java",
"Python",
"Lisp"
]
}
分享個JSON格式校驗網(wǎng)站
在線JSON校驗格式化工具(Be JSON)
JSON的基本操作
JSON的基本操作通常涉及以下幾個方面:
創(chuàng)建JSON對象: 可以使用編程語言提供的函數(shù)、類或庫來創(chuàng)建JSON對象。通常,這些函數(shù)或方法接受鍵值對作為參數(shù),用于指定JSON對象的屬性和對應的值。解析JSON字符串: 將JSON字符串解析為相應的數(shù)據(jù)結(jié)構(gòu),如對象、數(shù)組或基本數(shù)據(jù)類型。編程語言提供相應的解析函數(shù)或方法,可以將JSON字符串轉(zhuǎn)換為可操作的數(shù)據(jù)對象。生成JSON字符串: 將數(shù)據(jù)對象轉(zhuǎn)換為JSON字符串的表示形式,以便于傳輸、存儲或與其他系統(tǒng)進行交互。編程語言提供相應的函數(shù)或方法,可以將數(shù)據(jù)對象轉(zhuǎn)換為符合JSON格式規(guī)范的字符串。訪問和修改JSON對象的屬性: 通過鍵訪問JSON對象的屬性,并可以對其進行修改??梢允褂镁幊陶Z言提供的API來訪問、讀取和修改JSON對象的屬性值。遍歷JSON數(shù)組: 遍歷JSON數(shù)組中的元素,逐個訪問和處理數(shù)組中的數(shù)據(jù)項。使用循環(huán)結(jié)構(gòu)來遍歷數(shù)組,根據(jù)索引或迭代器獲取數(shù)組中的每個元素。嵌套JSON操作: 處理嵌套的JSON結(jié)構(gòu),包括訪問、修改和操作嵌套的對象或數(shù)組??梢允褂眠f歸、循環(huán)等方法來處理嵌套的JSON結(jié)構(gòu)。序列化和反序列化(重點): 將JSON對象序列化為字符串,或?qū)SON字符串反序列化為對象。序列化是將數(shù)據(jù)對象轉(zhuǎn)換為JSON字符串,反序列化是將JSON字符串轉(zhuǎn)換為數(shù)據(jù)對象。(本文主要介紹C語言的JSON庫來進行序列化和反序列化)
下面是一個C庫,用來完成本文教學
?cJSON.chttps://www.yuque.com/attachments/yuque/0/2023/txt/35243076/1687951166715-b8398dec-d697-4507-b49e-1e2ea5595ce9.txt?cJSON.hhttps://www.yuque.com/attachments/yuque/0/2023/txt/35243076/1687951166713-f66a28ef-8aaa-4fb0-8f7c-7fa49d94b608.txt
下面兩篇文章也能幫助我們完成JSON序列化和JSON反序列化的操作
cJSON 使用詳解_無痕眼淚的博客-CSDN博客由于c語言中,沒有直接的字典,字符串數(shù)組等數(shù)據(jù)結(jié)構(gòu),所以要借助結(jié)構(gòu)體定義,處理json。如果有對應的數(shù)據(jù)結(jié)構(gòu)就方便一些, 如python中用json.loads(json)就把json字符串轉(zhuǎn)變?yōu)閮?nèi)建的數(shù)據(jù)結(jié)構(gòu)處理起來比較方便。一個重要概念:在cjson中,json對象可以是json,可以是字符串,可以是數(shù)字。。。cjson數(shù)據(jù)結(jié)構(gòu)定義:#d..._cjsonhttps://blog.csdn.net/qq_32172673/article/details/88305781
https://www.cnblogs.com/liunianshiwei/p/6087596.htmlhttps://www.cnblogs.com/liunianshiwei/p/6087596.html
編譯注意事項
編譯cJSON庫時候,gcc需要增加? -lm 選項,動態(tài)鏈接math庫。
關(guān)鍵接口的梳理
/* 類型定義 */
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6
/* CJSON核心結(jié)構(gòu)體 */
typedef struct cJSON {
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
int type; /* 節(jié)點的類型,取值是上面的6種 */
char *valuestring; /* 如果類型是cJSON_String,那么值會被存到這里 */
int valueint; /* 如果類型是cJSON_Number,且是整型,那么值會被存到這里 */
double valuedouble; /* 如果類型是cJSON_Number,且是浮點型,那么值會被存到這里 */
char *string; /* 鍵*/
} cJSON;
/****************************通用接口****************************/
//把傳入的字符串轉(zhuǎn)成cJSON的結(jié)構(gòu)(反序列化)
cJSON *cJSON_Parse(const char *value);
//把cJSON結(jié)構(gòu)轉(zhuǎn)成字符串(序列化),調(diào)用后需要配合free接口釋放malloc的內(nèi)存
char *cJSON_Print(cJSON *item);
//無格式化序列化,節(jié)省內(nèi)存,調(diào)用后需要配合free接口釋放malloc的內(nèi)存
char *cJSON_PrintUnformatted(cJSON *item);
//釋放節(jié)點的內(nèi)存,防止內(nèi)存泄露
void cJSON_Delete(cJSON *c);
/****************************反序列化相關(guān)接口****************************/
//獲取數(shù)組的大小
int cJSON_GetArraySize(cJSON *array);
//從array數(shù)組中獲取第item個子節(jié)點
cJSON *cJSON_GetArrayItem(cJSON *array,int item);
//獲取object大節(jié)點名字叫string的子節(jié)點
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
//判斷object大節(jié)點中是否有名字叫string的小節(jié)點
int cJSON_HasObjectItem(cJSON *object,const char *string);
/****************************序列化相關(guān)接口****************************/
//創(chuàng)建一個普通節(jié)點
cJSON *cJSON_CreateObject(void);
//創(chuàng)建一個數(shù)組節(jié)點
cJSON *cJSON_CreateArray(void);
//把item節(jié)點增加到array的數(shù)組節(jié)點中
void cJSON_AddItemToArray(cJSON *array, cJSON *item);
//把item節(jié)點增加到object中作為子節(jié)點,item節(jié)點的鍵名為string
void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
//創(chuàng)建各種類型的cJSON節(jié)點
cJSON *cJSON_CreateNull(void);
cJSON *cJSON_CreateTrue(void);
cJSON *cJSON_CreateFalse(void);
cJSON *cJSON_CreateBool(int b);
cJSON *cJSON_CreateNumber(double num);
cJSON *cJSON_CreateString(const char *string);
cJSON *cJSON_CreateArray(void);
cJSON *cJSON_CreateObject(void);
序列化
使用cJSON庫序列化出下面的JSON內(nèi)容
{
"name": "小明",
"age": 14,
"gender": true,
"height": 1.65,
"grade": null,
"skills": [
"JavaScript",
"Java",
"Python",
"Lisp"
]
}
反序列化
使用cJSON庫對下面的JSON文件進行反序列化操作。ver和login的子節(jié)點直接打印即可,data的數(shù)據(jù)節(jié)點解析后形成鏈表存儲(將下面內(nèi)容存為文件,讀取后解析即可)。
{
"ver": "1.0",
"login": {
"user": "zhangsan",
"pwd": 1234
},
"data": [{
"key": 1,
"type": 2,
"val": "10"
},
{
"key": 2,
"type": 1,
"val": "0"
},
{
"key": 3,
"type": 3,
"val": "22.5"
}
]
}
注意:上面的所有val值都是string類型,解析出來存到節(jié)點前,需要根據(jù)type的類型來進行轉(zhuǎn)換,按照相應的類型存儲到共用體中。
提示:對于數(shù)據(jù)解析后,形成新的節(jié)點存放鏈表,最好的方式是為每個節(jié)點分配單獨的內(nèi)存。例:
struct data {
int key;
int type;
union val_t val;
struct list_head list;
};
struct data *node = (struct data *)malloc(sizeof(struct data));
node->xxx = xxx;
插入鏈表即可
答案和解析
序列化答案
#include
#include "cJSON.h"
#include
#include
#include
#include
#include
int main(int argc, char const *argv[])
{
// 序列化
cJSON *root = cJSON_CreateObject(); // 創(chuàng)建根節(jié)點
cJSON *age = cJSON_CreateNumber(14); // 創(chuàng)建一個數(shù)值類型的節(jié)點
cJSON_AddItemToObject(root, "age", age); // 將age節(jié)點添加到root對象中,鍵名為"age"
// 增加數(shù)組節(jié)點
cJSON *arr = cJSON_CreateArray(); // 創(chuàng)建一個數(shù)組類型的節(jié)點
cJSON_AddItemToArray(arr, cJSON_CreateString("JavaScript")); // 向數(shù)組中添加一個字符串節(jié)點
cJSON_AddItemToArray(arr, cJSON_CreateString("Java")); // 向數(shù)組中添加一個字符串節(jié)點
cJSON_AddItemToArray(arr, cJSON_CreateString("Python")); // 向數(shù)組中添加一個字符串節(jié)點
cJSON_AddItemToObject(root, "skills", arr); // 將數(shù)組節(jié)點添加到root對象中,鍵名為"skills"
// 輸出內(nèi)容
char *p = cJSON_PrintUnformatted(root); // 將JSON對象轉(zhuǎn)換為字符串表示形式
printf("root = %s\n", p);
free(p);
cJSON_Delete(root); // 釋放JSON對象占用的內(nèi)存
return 0;
}
反序列化答案
第一種思路
#include
#include "cJSON.h"
#include
#include
#include
#include
#include
#include "list.h"
#include
#define MAX 1024
union val_t
{
int i_val;
float f_val;
char *s_val[MAX];
};
struct data {
int key;
int type;
union val_t val;
struct list_head list;
};
int main(int argc, char const *argv[])
{
// 構(gòu)造鏈表
struct list_head head;
INIT_LIST_HEAD(&head);
struct data mydate[10]; // 創(chuàng)建結(jié)構(gòu)體數(shù)組
// 讀取文件內(nèi)容到緩沖區(qū)
int fd = open("data.json", O_RDONLY);
if (fd < 0)
{
perror("open err");
return -1;
}
char buf[MAX] = {0};
size_t len = read(fd, buf, MAX);
if (len < 0)
{
perror("open err");
return -1;
}
// 反序列化動作
cJSON *root = cJSON_Parse(buf); // 把傳入的字符串轉(zhuǎn)成cJSON的結(jié)構(gòu)(反序列化)
if (root == NULL)
{
printf("cJSON_Parse err.");
return -1;
}
// 開始摘取數(shù)據(jù)
cJSON *item;
cJSON *keyitem;
cJSON *typeitem;
cJSON *valitem;
item = cJSON_GetObjectItem(root, "ver"); // 獲取root的ver子節(jié)點
printf("%s : %s\n", item->string, item->valuestring);
cJSON *login = cJSON_GetObjectItem(root, "login");
cJSON *user = cJSON_GetObjectItem(login, "user");
cJSON *pwd = cJSON_GetObjectItem(login, "pwd");
printf("%s :\n", login->string);
printf("%s : %s\n", user->string, user->valuestring);
printf("%s : %d\n", pwd->string, pwd->valueint);
// 解析數(shù)組節(jié)點
cJSON *data;
data = cJSON_GetObjectItem(root, "data");
printf("%s :\n", data->string);
int count = cJSON_GetArraySize(data); // 獲取數(shù)組大小用來進行遍歷
for (size_t i = 0; i < count; i++)
{
cJSON *tmp = cJSON_GetArrayItem(data, i); // 獲取數(shù)組節(jié)點中的第 i 個元素
keyitem = cJSON_GetObjectItem(tmp, "key");
typeitem = cJSON_GetObjectItem(tmp, "type");
valitem = cJSON_GetObjectItem(tmp, "val");
printf("key : %d\n", keyitem->valueint);
printf("type : %d\n", typeitem->valueint);
printf("val : %s\n", valitem->valuestring);
mydate[i].key = keyitem->valueint; // 設(shè)置key值
mydate[i].type = typeitem->valueint; // 設(shè)置類型
strcpy(mydate[i].val.s_val, valitem->valuestring); // 將值拷貝到val數(shù)組
list_add(&mydate[i].list, &head); // 將結(jié)構(gòu)體添加到鏈表中
}
// 遍歷鏈表并輸出結(jié)果
struct list_head *pos;
struct data *newtmp;
list_for_each(pos, &head)
{
newtmp = list_entry(pos, struct data, list);
printf("key = %d, type = %d, val = %s\n", newtmp->key, newtmp->type, newtmp->val.s_val);
}
list_del(pos);
cJSON_Delete(root); // 釋放JSON對象占用的內(nèi)存
return 0;
}
第二種思路
#include
#include
#include
#include "cJSON.h"
#include "list.h"
//定義共用體
typedef int BOOL;
union val_t
{
BOOL b_val; //bool類型存儲空間
int i_val; //整形值存儲空間
float f_val; //浮點值存儲空間
};
//定義結(jié)構(gòu)體
struct student
{
int key;
int type;
union val_t val;
struct list_head list;//指針域
};
int main(int argc, char const *argv[])
{
struct list_head head;
INIT_LIST_HEAD(&head);
char * jsonStr = "{\"ver\":\"1.0\",\"login\":{\"user\":\"zhangsan\",\"pwd\":1234},\"data\":[{\"key\":1,\"type\":2,\"val\":\"10\"},{\"key\":2,\"type\":1,\"val\":\"0\"},{\"key\":3,\"type\":3,\"val\":\"22.5\"}]}";
cJSON * root = NULL;
cJSON * item = NULL;//cjson對象
//把傳入的字符串轉(zhuǎn)成cJSON的結(jié)構(gòu)(反序列化)
root = cJSON_Parse(jsonStr);//取出root對象(根節(jié)點)
if (!root)
{
printf("Error before: [%s]\n",cJSON_GetErrorPtr());
return -1;
}
else
{
printf("轉(zhuǎn)換成功!\n");
//獲取版本號--ver
item = cJSON_GetObjectItem(root, "ver");
printf("版本號%s:%s\n",item->string,item->valuestring);
//獲取帳號密碼
item = cJSON_GetObjectItem(root, "login");
cJSON * myuser = cJSON_GetObjectItem(item, "user");
printf("帳號%s:%s --- ",myuser->string,myuser->valuestring);
cJSON * mypwd = cJSON_GetObjectItem(item, "pwd");
printf("密碼%s:%d\n",mypwd->string,mypwd->valueint);
cJSON * myData = cJSON_GetObjectItem(root, "data");//root節(jié)點下的data節(jié)點
item = myData->child;//item是數(shù)組或?qū)ο蟮淖庸?jié)點,即data節(jié)點下的每一個小的花括號節(jié)點,或者可以用cJSON *cJSON_GetArrayItem(cJSON *array,int item)獲取數(shù)組中的子節(jié)點(花括號節(jié)點)
printf("data數(shù)據(jù)列表:\n");
while(item != NULL)
{
//取出data里的每一個花括號里的每一個小元素的值:即(key,type,val)的值
cJSON * mykey = cJSON_GetObjectItem(item, "key");
printf("鍵:%d ",mykey->valueint);
cJSON * mytype = cJSON_GetObjectItem(item, "type");
printf("類型:%d ",mytype->valueint);
cJSON * myval = cJSON_GetObjectItem(item, "val");//注意val的數(shù)據(jù)類型
printf("值:%s\n",myval->valuestring);
if(mykey != NULL && mytype != NULL && myval != NULL)
{
// printf("取值成功!以鏈表方式存儲\n");
//將解析的數(shù)據(jù)放入鏈表中
struct student * stu = (struct student *)malloc(sizeof(struct student));//記得釋放內(nèi)存
stu->key = mykey->valueint;
stu->type = mytype->valueint;
if(mytype->valueint == 1)
{
int valnum = atoi(myval->valuestring);
stu->val.i_val = valnum;
}
else if(mytype->valueint == 2)
{
int valnum = atoi(myval->valuestring);
stu->val.i_val = valnum;
}
else if(mytype->valueint == 3)
{
int valnum = atof(myval->valuestring);
stu->val.f_val = valnum;
}
// stu->val.i_val = myval->valuestring;
//頭插法插入
list_add(&stu->list,&head);
}
item = item->next;
}
//遍歷打印
struct list_head *pos;//是指向一個結(jié)構(gòu)體的一個指針域的指針
struct student *tmp;//是指向整個結(jié)構(gòu)體的指針
// printf("init list\n");
printf("鏈表數(shù)據(jù):\n");
list_for_each(pos, &head)
{
// sleep(3);
tmp = list_entry(pos, struct student, list);//可以從指針域偏移到整個結(jié)構(gòu)體,拿到整個結(jié)構(gòu)體的首地址,因此能夠拿到屬于該指針域的數(shù)據(jù)域
if(tmp->type == 1)
{
printf("key=%d, type=%d, val=%d\n", tmp->key, tmp->type, tmp->val.i_val);
}
else if(tmp->type == 2)
{
printf("key=%d, type=%d, val=%d\n", tmp->key, tmp->type, tmp->val.b_val);
}
else if(tmp->type == 3)
{
printf("key=%d, type=%d, val=%.2f\n", tmp->key, tmp->type, tmp->val.f_val);
}
}
printf("\n");
}
cJSON_Delete(root);
return 0;
}
柚子快報激活碼778899分享:一文搞懂JSON
文章鏈接
本文內(nèi)容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。