1.cJSON compilation and installation
- GitHub address: https://github.com/DaveGamble/cJSON
- download
git clone https://github.com/DaveGamble/cJSON.git
Compile with reference to Readme
You can directly use cjson H and cjson C add to source file
- Compile instruction
gcc test.c cJSON.c -lm
2. Data structure definition
2.1cJSON structure
/* The cJSON structure: */ typedef struct cJSON { /* next/prev allow you to walk array/object chains. Alternatively, use Get ArraySize/GetArrayItem/GetObjectItem */ struct cJSON *next; struct cJSON *prev; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ struct cJSON *child; /* The type of the item, as above. */ int type; /* The item's string, if type==cJSON_String and type == cJSON_Raw */ char *valuestring; /* The item's number, if type==cJSON_Number */ int valueint; /* The item's number, if type==cJSON_Number */ double valuedouble; 12 /* The item's name string, if this item is the child of, or is in the listof subitems of an object. */ char *string; } cJSON;
next and prev are used to traverse the forward and backward linked list pointers of the array or object chain; Child points to the child node of the array or object; Type is the type of value; valuestring is a string value; valueint is an integer value; valuedouble is a floating-point value; String is the name of the key.
2.2 types supported by JSON
/* cJSON Types: */ #define cJSON_Invalid (0) #define cJSON_False (1 << 0) #define cJSON_True (1 << 1) #define cJSON_NULL (1 << 2) #define cJSON_Number (1 << 3) #define cJSON_String (1 << 4) #define cJSON_Array (1 << 5) #define cJSON_Object (1 << 6) #define cJSON_Raw (1 << 7) /* raw json */
- valuestring, when the type is cJSON_String or cjson_ When raw, the value of value is NULL when the type is inconsistent
- valueint, when the type is cJSON_Number, the value of value
- valuedouble, when the type is cjson_ When number, the value of value (mainly used)
- string represents the value of the key in the key value pair
3. Key functions
3.1 cJSON_Parse
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ extern cJSON *cJSON_Parse(const char *value);
- Function: serialize a JSON string according to the structure of the cJSON structure, and open up a memory in the heap to store the cJSON structure. (string passed into c language)
- Return value: successfully returns a pointer to cJSON in the memory block, and fails to return NULL.
3.2 cJSON_Delete
/* Delete a cJSON entity and all subentities. */ extern void cJSON_Delete(cJSON *c);
- Function: release the memory of cJSON structure in the heap.
- Return value: None
- Note: when using cJSON_ After parse() obtains the cJSON pointer, if it is no longer used, you need to call cJSON_Delete() frees it, otherwise it will cause a memory leak.
3.3 cJSON_Print
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ extern char *cJSON_Print(const cJSON *item);
- Function: parse cjson data into JSON strings, and open up a memory space of char * in the heap to store JSON strings. cJSON_PrintUnformatted() and cJSON_Print() is similar, except that the printout is not formatted, but just a string data.
- Return value: a char * pointer is returned successfully, which points to the JSON string in the heap, and NULL is returned in failure.
- Note: through cJSON_Print() can print all cJSON objects in the cJSON linked list, but you need to manually release the corresponding resource: free(char *).
3.4 cJSON_Version
/* returns the version of cJSON as a string */ extern const char* cJSON_Version(void);
- Function: get the version number of the currently used cJSON library.
- Return value: returns a string of data.
3.5 cJSON_GetArrayItem
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ extern cJSON *cJSON_GetArrayItem(const cJSON *array, int item);
- Function: find the cJSON object whose key is string from the cJSON chain of object.
- Return value: a pointer to the structure of cJSON type is returned successfully, and NULL is returned in failure.
- And cJSON_GetObjectItem() has the following interfaces:
/* Returns the number of items in an array (or object). */ extern int cJSON_GetArraySize(const cJSON *array);
/* Get item "string" from object. Case insensitive. */ extern cJSON *cJSON_GetObjectItem(const cJSON *object, const char *string) ; extern int cJSON_HasObjectItem(const cJSON *object, const char *string);
4. Introduction to all functions
5. Introduction to use examples
1. Test file 1: cjson_test.c
- Compilation instruction: GCC cjson c cjson_ test. c -o cjson_ test -lm
- File content
test1() / / create a json file and parse it
test2() / / read the local json file
test3() / / add, delete, query and modify json
#include <stdio.h> #include <stdlib.h> #include "cJSON.h" #include <string.h> /** { "name": "milo", "age": 80, "professional": {major "english": 4, "putonghua": 2, "computer": 4 }, "languages": ["C++", "C"], "phone": { "number": "18620823143", "type": "home" }, "courses": [{ "name": "Linux kernel development", "price": "7.7" }, { "name": "Linux server development", "price": "8.0" }], "vip": true, "address": null } */ //Print CJSON void printfJson(cJSON *json) { if (NULL == json) { return; } char *cjson=cJSON_Print(json);//Deep copy printf("json:%s\n", cjson); free(cjson); } //release void freeJson(cJSON *json) { if (json != NULL) { cJSON_Delete(json); } } //Create JSON cJSON * createJson() { cJSON *json_root=cJSON_CreateObject(); cJSON_AddItemToObject(json_root, "name", cJSON_CreateString("milo")); cJSON_AddNumberToObject(json_root, "age", 80); cJSON *json_professional=cJSON_CreateObject(); cJSON_AddItemToObject(json_professional,"english", cJSON_CreateNumber(4)); cJSON_AddItemToObject(json_professional,"putonghua", cJSON_CreateNumber(2)); cJSON_AddItemToObject(json_professional,"computer", cJSON_CreateNumber(3)); cJSON *json_languages=cJSON_CreateArray(); cJSON_AddItemToArray(json_languages, cJSON_CreateString("C++")); cJSON_AddItemToArray(json_languages, cJSON_CreateString("C")); cJSON *json_phone=cJSON_CreateObject(); cJSON_AddItemToObject(json_phone,"number", cJSON_CreateString("18620823143")); cJSON_AddItemToObject(json_phone,"type", cJSON_CreateString("home")); cJSON *json_courses = cJSON_CreateArray(); cJSON* json_pItem1 = cJSON_CreateObject(); cJSON_AddItemToObject(json_pItem1, "name", cJSON_CreateString("Linux kernel development")); cJSON_AddNumberToObject(json_pItem1, "price", 7.7); cJSON_AddItemToArray(json_courses, json_pItem1); cJSON* json_pItem2 = cJSON_CreateObject(); cJSON_AddItemToObject(json_pItem2, "name", cJSON_CreateString("Linux server development")); cJSON_AddNumberToObject(json_pItem2, "price", 8.8); cJSON_AddItemToArray(json_courses, json_pItem2); cJSON_AddItemToObject(json_root, "professional", json_professional); cJSON_AddItemToObject(json_root, "languages", json_languages); cJSON_AddItemToObject(json_root, "phone", json_phone); cJSON_AddItemToObject(json_root, "courses", json_courses); cJSON_AddBoolToObject(json_root, "vip", 1); cJSON_AddNullToObject(json_root, "address"); return json_root; } //Add to existing JSON //"hobby": ["Basketball", "Football", "badminton"], void addDataToJson(cJSON *json) { if (NULL == json) { return; } cJSON *hobby=cJSON_CreateArray(); cJSON_AddItemToArray(hobby, cJSON_CreateString("Basketball")); cJSON_AddItemToArray(hobby, cJSON_CreateString("Football")); cJSON_AddItemToArray(hobby, cJSON_CreateString("badminton")); /* CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); */ cJSON_AddItemToObject(json, "hobby", hobby); printfJson(json); } //modify //"hobby": ["Basketball", "Football", "badminton"], //Change to //"hobby": ["Skating", "dance"], void updateDataToJson(cJSON *json) { if (NULL == json) { return; } cJSON *hobby=cJSON_CreateArray(); cJSON_AddItemToArray(hobby, cJSON_CreateString("Skating")); cJSON_AddItemToArray(hobby, cJSON_CreateString("dance")); /* CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); */ cJSON_ReplaceItemInObject(json, "hobby", hobby); printfJson(json); } //delete //"hobby": ["Skating", "dance"], void deleteDataToJson(cJSON *json) { if (NULL == json) { return; } /* CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); */ cJSON_DetachItemFromObject(json, "hobby"); printfJson(json); } //Parsing JSON void analysisJsonObj(cJSON *json) { if (NULL == json) { return; } cJSON *json_name = cJSON_GetObjectItem(json, "name"); printf("root[%s:%s]\n", json_name->string, json_name->valuestring); cJSON *json_age = cJSON_GetObjectItem(json, "age"); printf("root[%s:%d]\n", json_age->string, json_age->valueint); cJSON *json_professional = cJSON_GetObjectItem(json, "professional"); cJSON *json_professional_child = json_professional->child; while (json_professional_child != NULL) { printf("%s[%s:%d]\n", json_professional->string, json_professional_child->string, json_professional_child->valueint); json_professional_child = json_professional_child->next; } cJSON *json_languages = cJSON_GetObjectItem(json, "languages"); if (json_languages) { int size = cJSON_GetArraySize(json_languages); printf("%s size:%d\n", json_languages->string, size); for (int i = 0; i < size; i++) { cJSON *json_languages_child =cJSON_GetArrayItem(json_languages, i); printf("%s[%d:%s]\n", json_languages->string, i, json_languages_child->valuestring); } } cJSON *json_phone = cJSON_GetObjectItem(json, "phone"); cJSON *json_phone_number = cJSON_GetObjectItem(json_phone,"number"); cJSON *json_phone_type = cJSON_GetObjectItem(json_phone,"type"); printf("%s[%s:%s]\n", json_phone->string, json_phone_number->string, json_phone_number->valuestring); printf("%s[%s:%s]\n", json_phone->string, json_phone_type->string, json_phone_type->valuestring); cJSON *json_courses = cJSON_GetObjectItem(json, "courses"); if (json_courses) { int size = cJSON_GetArraySize(json_courses); printf("%s size:%d\n", json_courses->string, size); for(int i=0;i<size;i++) { cJSON *json_array = cJSON_GetArrayItem(json_courses, i); if (json_array) { cJSON *json_course_name = cJSON_GetObjectItem(json_array,"name"); cJSON *json_course_price = cJSON_GetObjectItem(json_array,"price"); printf("%s[%s:%.1lf]\n", json_courses->string, json_course_name->string, json_course_name->valuedouble); printf("%s[%s:%.1lf]\n", json_courses->string, json_course_price->string, json_course_price->valuedouble); } } } cJSON *json_vip = cJSON_GetObjectItem(json, "vip"); if (json_vip->type == cJSON_True) { printf("root[%s:true]\n", json_vip->string); } else if (json_vip->type == cJSON_False) { printf("root[%s:false]\n", json_vip->string); } else { printf("root[%s:false]\n", json_vip->string); } cJSON *json_address = cJSON_GetObjectItem(json, "address"); if (json_address->type ==cJSON_NULL) { printf("root[%s:null]\n", json_address->string); } } static void printJsonObjvalue(const cJSON *json) { if (NULL == json) { printf("NULL object!\n"); return; } switch (json->type) { case cJSON_False: printf("%s: false\n", json->string); break; case cJSON_True: printf("%s: true\n", json->string); break; case cJSON_NULL: printf("%s: cJSON_NULL\n", json->string); break; case cJSON_Number: printf("%s: %d, %f\n", json->string, json->valueint, json->valuedouble); break; case cJSON_String: printf("%s: %s\n", json->string, json->valuestring); break; case cJSON_Array: printf("%s: cJSON_Array\n", json->string); break; case cJSON_Object: printf("%s: cJSON_Object\n", json->string); break; default: printf("unknown type\n"); break; } } void analysisJsonPrint(cJSON *json) { if (NULL == json) { return; } cJSON *json_name = cJSON_GetObjectItem(json, "name"); printJsonObjvalue(json_name); cJSON *json_age = cJSON_GetObjectItem(json, "age"); printJsonObjvalue(json_age); cJSON *json_professional = cJSON_GetObjectItem(json, "professional"); cJSON *json_professional_child = json_professional->child; while (json_professional_child != NULL) { printJsonObjvalue(json_professional_child); json_professional_child = json_professional_child->next; } cJSON *json_languages = cJSON_GetObjectItem(json, "languages"); if (NULL == json_languages) { int size = cJSON_GetArraySize(json_languages); printf("%s size:%d\n", json_languages->string, size); for (int i = 0; i < size; i++) { cJSON *json_languages_child = cJSON_GetArrayItem(json_languages, i); printJsonObjvalue(json_languages_child); } } cJSON *json_phone = cJSON_GetObjectItem(json, "phone"); cJSON *json_phone_number = cJSON_GetObjectItem(json_phone,"number"); cJSON *json_phone_type = cJSON_GetObjectItem(json_phone,"type"); printJsonObjvalue(json_phone_number); printJsonObjvalue(json_phone_type); cJSON *json_courses = cJSON_GetObjectItem(json, "courses"); if (json_courses) { int size = cJSON_GetArraySize(json_courses); printf("%s size:%d\n", json_courses->string, size); for(int i=0;i<size;i++) { cJSON *arrayItem = cJSON_GetArrayItem(json_courses, i); if (NULL != arrayItem) { cJSON *json_course_name = cJSON_GetObjectItem(arrayItem,"name"); cJSON *json_course_price = cJSON_GetObjectItem(arrayItem,"price"); printJsonObjvalue(json_course_name); printJsonObjvalue(json_course_price); } } } cJSON *json_vip = cJSON_GetObjectItem(json, "vip"); printJsonObjvalue(json_vip); cJSON *json_address = cJSON_GetObjectItem(json, "address"); printJsonObjvalue(json_address); } //Read JSON cJSON* readJsonFile(char *fileName) { if (NULL == fileName) { return NULL; } FILE *fp = NULL; cJSON *json = NULL; char line[1024] = {0}; char *data = NULL; //Open a text file. The file must exist and can only be read fp = fopen(fileName, "r"); if (NULL != fp) { //End of seek fseek(fp, 0, SEEK_END); //Read file size long len = ftell(fp); //seek start bit value fseek(fp, 0, SEEK_SET); data = (char*)malloc(len + 1); fread(data, 1, len, fp); fclose(fp); } printf("readJsonFile data:%s\n", data); cJSON *json_root = cJSON_Parse(data); if (NULL == json_root) { printf("cJSON_Parse error:%s\n", cJSON_GetErrorPtr()); } if (NULL != data) { free(data); } return json_root; } //Save JSON void writeJsonFile(char *fileName, cJSON *json) { if (NULL == json || NULL == fileName) { return; } char *cjson=cJSON_Print(json); FILE *fp = NULL; //Create a new text file. The existing file will empty its contents and allow reading and writing fp = fopen(fileName, "w+"); if (NULL != fp) { fwrite(cjson, strlen(cjson),1,fp); fclose(fp); } if (NULL != cjson) { free(cjson); } } void test1() {//Create a json file and parse it cJSON *json_root = createJson();//Create json file //Print printfJson(json_root); //Parsing json analysisJsonObj(json_root); //Parsing json analysisJsonPrint(json_root); freeJson(json_root); } void test2() { //Read the local json file char *fileName = "./person.json"; //Read json cJSON *json_root = readJsonFile(fileName); //Parsing json analysisJsonObj(json_root); //Parsing json analysisJsonPrint(json_root); //Write json file writeJsonFile(fileName, json_root); //release freeJson(json_root); } //Addition, deletion and modification void test3() {//Add, delete, query and modify json cJSON *json_root = createJson(); addDataToJson(json_root); updateDataToJson(json_root); deleteDataToJson(json_root); freeJson(json_root); } int main(int argc, char *argv[]) { // printf("-----------------------------------\n"); // test1(); printf("-----------------------------------\n"); test2(); printf("-----------------------------------\n"); // test3(); // printf("-----------------------------------\n"); return 0; }
JSON file: person json
{ "name": "milo", "age": 80, "professional": { "english": 4, "putonghua": 2, "computer": 3 }, "languages": ["C++", "C"], "phone": { "number": "18620823143", "type": "home" }, "courses": [{ "name": "Linux kernel development", "price": 7.700000 }, { "name": "Linux server development", "price": 8.800000 }], "vip": true, "address": null }
2. Test file 2: comment_test.c
- Compilation instruction: GCC cjson c comment_ test. c -o comment_ test -lm
- File content
test1() / / convert the comment structure to json format
test2() / / read the local json file
code:
#include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include "cJSON.h" #include <string.h> //comment typedef struct COMMENT { int user_id; int msg_id; char* comment; int click_count; int like_count; int reply_count; int is_new_reply; long add_time; } COMMENT; //Gets the current time in milliseconds long getCurrentTime() { struct timeval tv; gettimeofday(&tv,NULL); //millisecond long time_sec = tv.tv_sec*1000 + tv.tv_usec/1000; return time_sec; } //Print CJSON void printfJson(cJSON *json) { if (NULL == json) { return; } char *cjson=cJSON_Print(json);//Deep copy printf("json:%s\n", cjson); free(cjson); } void freeComment(COMMENT *comment) { if (comment != NULL) { if (comment->comment != NULL) { free(comment->comment); comment->comment = NULL; } free(comment); comment = NULL; } } void freeJson(cJSON *json) { if (json != NULL) { cJSON_Delete(json); } } /** json object { "user_id":1, "msg_id":1, "comment":"json", "click_count":0, "like_count":0, "reply_count":0, "is_new_reply":0, "add_time":0, } */ //After passing the comment, create the json class //Convert structure to cJSON cJSON *convertToJson(COMMENT *comment) { if (comment == NULL) { return NULL; } //Build json //char *cjson = "{\"name\":\"milo\"}";// To build json in this way, you need to use cJSON_Parse() is constructed by this method to parse the string into a cJSON structure //cJSON *json = cJSON_Parse(cjson);// The JSON created in this way has data //Create json //Convert the structure into json protocol, save or provide it to the client cJSON *json=cJSON_CreateObject();//The json created in this way has no data //Add "user_id" to the "json" node cJSON_AddNumberToObject(json, "user_id", comment->user_id);//AddNumber means that the corresponding type is a number type, and the number type includes integer and floating point cJSON_AddNumberToObject(json, "msg_id", comment->msg_id); cJSON_AddItemToObject(json, "comment", cJSON_CreateString(comment->comment));//Here, the structure data is converted to json cJSON_AddNumberToObject(json, "click_count", comment->click_count); cJSON_AddNumberToObject(json, "like_count", comment->like_count); cJSON_AddNumberToObject(json, "reply_count", comment->reply_count); cJSON_AddNumberToObject(json, "is_new_reply", comment->is_new_reply); cJSON_AddNumberToObject(json, "add_time", comment->add_time); return json; } //Assign cJSON to structure //For example, here is the json format that the client gets from the server COMMENT* convertToComment(cJSON *json) { if (NULL == json) { return NULL; } cJSON *json_user_id = cJSON_GetObjectItem(json, "user_id"); cJSON *json_msg_id = cJSON_GetObjectItem(json, "msg_id"); cJSON *json_comment = cJSON_GetObjectItem(json, "comment"); cJSON *json_click_count = cJSON_GetObjectItem(json, "click_count"); cJSON *json_like_count = cJSON_GetObjectItem(json, "like_count"); cJSON *json_reply_count = cJSON_GetObjectItem(json, "reply_count"); cJSON *json_is_new_reply = cJSON_GetObjectItem(json, "is_new_reply"); cJSON *json_add_time = cJSON_GetObjectItem(json, "add_time"); COMMENT *comment = (COMMENT *)malloc(sizeof(COMMENT)); comment->user_id = json_user_id->valueint; comment->msg_id = json_msg_id->valueint; comment->comment=(char *)malloc(256); memset(comment->comment, 0, 256); strcat(comment->comment, json_comment->valuestring); comment->click_count = json_click_count->valueint; comment->like_count = json_like_count->valueint; comment->reply_count = json_reply_count->valueint; comment->is_new_reply = json_is_new_reply->valueint; comment->add_time = (long)(json_add_time->valuedouble); return comment; } //Read json from file void readJsonFromData(char *data) { cJSON *json=cJSON_Parse(data); //Build data into cJSON structure //Print json printfJson(json); //Print json COMMENT* comment = convertToComment(json); //It is similar to unpacking json packages. For example, here is the json format that the client gets from the server if (comment != NULL) { comment->like_count = 77; // comment->reply_count = 99; // //Convert to json cJSON *childjson = convertToJson(comment); //Print json printfJson(childjson); //Release object freeComment(comment); // freeJson(childjson); } freeJson(json); } //Save JSON void writeJsonFile(cJSON *json) { if (NULL == json) { return; } char *cjson=cJSON_Print(json); FILE *fp = NULL; char *fileName = "./comment.json"; fp = fopen(fileName, "w+"); if (NULL != fp) { fwrite(cjson, strlen(cjson),1,fp); fclose(fp); } if (cjson != NULL) { free(cjson); } } //Read JSON void readJsonFile() { FILE *fp = NULL; char *out; char line[1024] = {0}; char *fileName = "./comment.json"; //Open a text file. The file must exist and can only be read fp = fopen(fileName, "r"); //End of seek fseek(fp, 0, SEEK_END); //Read file size long len = ftell(fp); //seek start bit value fseek(fp, 0, SEEK_SET); char *data = (char*)malloc(len + 1); fread(data, 1, len, fp); if (fp != NULL) { fclose(fp); } //read readJsonFromData(data); if (NULL != data) { free(data); } } //Got a comment object COMMENT *createComment() { COMMENT *comment = (COMMENT *)malloc(sizeof(COMMENT)); comment->user_id = 1; comment->msg_id = 10000; comment->comment=(char *)malloc(256); memset(comment->comment, 0, 256); sprintf(comment->comment, "I agree with you"); comment->click_count = 0; comment->like_count = 0; comment->reply_count = 0; comment->is_new_reply = 0; comment->add_time = getCurrentTime(); return comment; } void test1() { COMMENT *comment = createComment();//To create a comment object is to initialize the packet structure //Convert to json cJSON *json = convertToJson(comment);//Convert the structure to cJSON and return the json object //Save json writeJsonFile(json);//Save json locally freeComment(comment);//Release structure data freeJson(json);// } void test2() { //Read json readJsonFile(); } int main(int argc, char *argv[]) { test1(); test2(); return 0; }
JSON file: comment json
{ "user_id": 1, "msg_id": 10000, "comment": "I agree with you", "click_count": 0, "like_count": 0, "reply_count": 0, "is_new_reply": 0, "add_time": 1624628790079 }