├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── cjsonp ├── cjsonp.c ├── cjsonp_cmd_parser.c └── include │ ├── cjsonp.h │ └── cjsonp_cmd_parser.h ├── makefile └── test.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | 54 | build/ 55 | .vscode/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "cJSON"] 2 | path = cJSON 3 | url = https://github.com/DaveGamble/cJSON.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 geekheart 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cjsonp 2 | 这是一个基于cjson的库,cjson对于使用者来说比较繁琐。这个库调用起来比较方便、简洁。 3 | 4 | 借用了[jsonPath](https://github.com/json-path/JsonPath)的理念,但是还不能像[jsonPath](https://github.com/json-path/JsonPath)那样强大,目前只支持全路径匹配,且匹配的规则会有些许不同 5 | 6 | ## 运行例程 7 | 1. 首先,你需要clone本库 8 | ```shell 9 | $ git clone https://github.com/geekheart/cjsonp.git 10 | $ cd cjsonp 11 | $ git submodule init 12 | $ git submodule update 13 | ``` 14 | 2. 然后,确保你的环境里有gcc编译器和make工具 15 | ```shell 16 | $ gcc 17 | gcc: fatal error: no input files 18 | compilation terminated 19 | $ make 20 | make: *** No targets specified and no makefile found. Stop. 21 | ``` 22 | 3. 进入cjsonp文件夹里就可以make编译了 23 | ```shell 24 | $ make # 编译例程 25 | $ make run # 运行例程 26 | $ make clean # 清空编译生成的内容 27 | ``` 28 | 29 | ## 如何移植 30 | 本库核心部分cjsonp_cmd_parser没有用到任何库(包括libc),cjsonp部分则依赖cJSON。 31 | 将本库中的cjsonp文件夹直接复制到您的工程,即可使用。 32 | include本库后自动添加cJSON库 33 | 34 | ## API说明 35 | 解析的路径,路径规则:
36 | .表示子对象
37 | []用于数组对象
38 | 数组对象前后不用.
39 | 40 | ```c 41 | /** 42 | * @brief 从cjson对象中找到你需要的元素 43 | * 44 | * @param json_root cjson根对象 45 | * @param path 查找cjson的路径 46 | * @return cJSON* 返回的额元素对象 47 | */ 48 | cJSON* cjsonp_search(cJSON* json_root, const char *path); 49 | 50 | /** 51 | * @brief 删除cjson对象的元素 52 | * 53 | * @param json_root cjson根对象 54 | * @param path 删除cjson的路径 55 | * @return int 返回1成功,0失败 56 | */ 57 | int cjsonp_delete(cJSON *json_root, const char *path); 58 | 59 | /** 60 | * @brief 添加cjson元素到对象中 61 | * 62 | * @param json_root cjson根对象 63 | * @param path 添加cjson的路径 64 | * @param add_json 添加的cjson对象 65 | * @return int 返回1成功,0失败 66 | */ 67 | int cjsonp_add(cJSON *json_root, const char *path, cJSON *add_json); 68 | 69 | /** 70 | * @brief 替换cjson对象中的元素 71 | * 72 | * @param json_root cjson根对象 73 | * @param path 替换cjson的路径 74 | * @param rep_json 替换的cjson对象 75 | * @return int 返回1成功,0失败 76 | */ 77 | int cjsonp_replace(cJSON *json_root, const char *path, cJSON *rep_json); 78 | 79 | ``` -------------------------------------------------------------------------------- /cjsonp/cjsonp.c: -------------------------------------------------------------------------------- 1 | #include "cjsonp_cmd_parser.h" 2 | #include "cjsonp.h" 3 | #include 4 | #include 5 | 6 | #if CJSONP_DEBUG 7 | #include 8 | #define CJSONP_LOG() printf("\033[31mcjsonp: %d has been return\033[0m\n", __LINE__) 9 | #else 10 | #define CJSONP_LOG() 11 | #endif 12 | 13 | #define JSON_KEY_LEN 128 14 | 15 | #define CJSONP_ASSERT(x) \ 16 | if (x) \ 17 | { \ 18 | CJSONP_LOG(); \ 19 | goto end; \ 20 | } 21 | 22 | static cJSON *_cjsonp_find(cJSON **last_obj, cjsonp_tok_t *last_jsonp_tok, unsigned char last_err) 23 | { 24 | cjsonp_tok_t jsonp_tok = *last_jsonp_tok; 25 | cJSON *json_obj_before = *last_obj; 26 | char json_key[JSON_KEY_LEN] = {0}; 27 | int index; 28 | 29 | // 处理parse 30 | cjsonp_cmd_parser_update(&jsonp_tok); 31 | while (jsonp_tok.size != 0) 32 | { 33 | json_obj_before = *last_obj; 34 | *last_jsonp_tok = jsonp_tok; 35 | memset(json_key, 0, sizeof(json_key)); 36 | strncpy(json_key, jsonp_tok.json_ptr, jsonp_tok.size); 37 | switch (jsonp_tok.type) 38 | { 39 | case JSON_PARSER_STR: 40 | *last_obj = cJSON_GetObjectItem(*last_obj, json_key); 41 | break; 42 | case JSON_PARSER_NUM: 43 | index = atoi(json_key); 44 | *last_obj = cJSON_GetArrayItem(*last_obj, index); 45 | break; 46 | default: 47 | break; 48 | } 49 | cjsonp_cmd_parser_update(&jsonp_tok); 50 | if (last_err) 51 | { 52 | CJSONP_ASSERT(*last_obj == NULL && jsonp_tok.size != 0); 53 | } 54 | else 55 | { 56 | CJSONP_ASSERT(*last_obj == NULL); 57 | } 58 | } 59 | return json_obj_before; 60 | end: 61 | return NULL; 62 | } 63 | 64 | static cJSON* cjsonp_detach(cJSON *json_root, const char *path) 65 | { 66 | cJSON *json_parent = NULL; 67 | cJSON *json_obj = NULL; 68 | cjsonp_tok_t jsonp_tok; 69 | char res; 70 | 71 | // 输入断言 72 | CJSONP_ASSERT(json_root == NULL || path == NULL); 73 | 74 | // 初始化命令解析器 75 | res = cjsonp_cmd_parser_init(&jsonp_tok, path); 76 | CJSONP_ASSERT(!res); 77 | 78 | // 找到json子对象 79 | json_obj = json_root; 80 | json_parent = _cjsonp_find(&json_obj, &jsonp_tok, 0); 81 | CJSONP_ASSERT(json_parent == NULL || json_obj == NULL); 82 | 83 | // 分离子节点 84 | json_obj = cJSON_DetachItemViaPointer(json_parent, json_obj); 85 | 86 | return json_obj; 87 | end: 88 | return NULL; 89 | } 90 | 91 | cJSON *cjsonp_search(cJSON *json_root, const char *path) 92 | { 93 | char res; 94 | cjsonp_tok_t jsonp_tok; 95 | cJSON *json_obj = NULL; 96 | 97 | // 输入断言 98 | CJSONP_ASSERT(json_root == NULL || path == NULL); 99 | 100 | // 初始化命令解析器 101 | res = cjsonp_cmd_parser_init(&jsonp_tok, path); 102 | CJSONP_ASSERT(!res); 103 | 104 | json_obj = json_root; 105 | _cjsonp_find(&json_obj, &jsonp_tok, 0); 106 | 107 | return json_obj; 108 | end: 109 | return NULL; 110 | } 111 | 112 | int cjsonp_delete(cJSON *json_root, const char *path) 113 | { 114 | cJSON* detach = cjsonp_detach(json_root, path); 115 | CJSONP_ASSERT(detach == NULL); 116 | cJSON_Delete(detach); 117 | 118 | return 1; 119 | end: 120 | return 0; 121 | } 122 | 123 | int cjsonp_add(cJSON *json_root, const char *path, cJSON *add_json) 124 | { 125 | cJSON *json_obj = NULL; 126 | cjsonp_tok_t jsonp_tok; 127 | char res; 128 | char json_key[JSON_KEY_LEN] = {0}; 129 | int index; 130 | 131 | // 输入断言 132 | CJSONP_ASSERT(json_root == NULL || path == NULL || add_json == NULL); 133 | 134 | // 初始化命令析器 135 | res = cjsonp_cmd_parser_init(&jsonp_tok, path); 136 | CJSONP_ASSERT(!res); 137 | 138 | // 解析 139 | json_obj = json_root; 140 | json_obj = _cjsonp_find(&json_obj, &jsonp_tok, 1); 141 | CJSONP_ASSERT(json_obj == NULL); 142 | 143 | // 添加json 144 | strncpy(json_key, jsonp_tok.json_ptr, jsonp_tok.size); 145 | switch (jsonp_tok.type) 146 | { 147 | case JSON_PARSER_STR: 148 | CJSONP_ASSERT(cJSON_GetObjectItem(json_obj, json_key) != NULL); 149 | cJSON_AddItemToObject(json_obj, json_key, add_json); 150 | break; 151 | case JSON_PARSER_NUM: 152 | index = atoi(json_key); 153 | cJSON_InsertItemInArray(json_obj, index, add_json); 154 | break; 155 | default: 156 | break; 157 | } 158 | 159 | return 1; 160 | end: 161 | return 0; 162 | } 163 | 164 | int cjsonp_replace(cJSON *json_root, const char *path, cJSON *rep_json) 165 | { 166 | cJSON *json_obj = NULL; 167 | cJSON *json_parent = NULL; 168 | cjsonp_tok_t jsonp_tok; 169 | char res = 1; 170 | 171 | // 输入断言 172 | CJSONP_ASSERT(json_root == NULL || path == NULL || rep_json == NULL); 173 | 174 | // 初始化命令析器 175 | res = cjsonp_cmd_parser_init(&jsonp_tok, path); 176 | CJSONP_ASSERT(!res); 177 | 178 | // 解析 179 | json_obj = json_root; 180 | json_parent = _cjsonp_find(&json_obj, &jsonp_tok, 0); 181 | CJSONP_ASSERT(json_parent == NULL); 182 | 183 | // 替换json 184 | if (rep_json->string == NULL && json_obj->string != NULL) 185 | { 186 | rep_json->string = strdup(json_obj->string); 187 | } 188 | res = cJSON_ReplaceItemViaPointer(json_parent, json_obj, rep_json); 189 | 190 | return res; 191 | end: 192 | return 0; 193 | } 194 | 195 | 196 | 197 | int cjsonp_swap(cJSON *json_root, const char *json1_path, const char *json2_path) 198 | { 199 | cJSON* json1 = cjsonp_search(json_root, json1_path); 200 | cJSON* json2 = cjsonp_search(json_root, json2_path); 201 | cJSON* _json1 = cJSON_Duplicate(json1, 1); 202 | char* j = cJSON_Print(_json1); 203 | printf("%s", j); 204 | cJSON* _json2 = cJSON_Duplicate(json2, 1); 205 | cjsonp_replace(json_root, json1_path, _json2); 206 | cjsonp_replace(json_root, json2_path, _json1); 207 | return 1; 208 | } -------------------------------------------------------------------------------- /cjsonp/cjsonp_cmd_parser.c: -------------------------------------------------------------------------------- 1 | #include "cjsonp_cmd_parser.h" 2 | 3 | #ifndef NULL 4 | #ifdef __cplusplus 5 | #define NULL 0 6 | #else 7 | #define NULL ((void *)0) 8 | #endif 9 | #endif 10 | 11 | static unsigned long _strlen(const char *str) 12 | { 13 | unsigned long count = 0; 14 | if (str == NULL) 15 | { 16 | return 0; 17 | } 18 | while (*str != '\0' && *str != 0) 19 | { 20 | count++; 21 | str++; 22 | } 23 | return count; 24 | } 25 | char cjsonp_cmd_parser_init(cjsonp_tok_t *jsonp_tok, const char *parse_str) 26 | { 27 | if (parse_str == NULL) 28 | { 29 | return 0; 30 | } 31 | jsonp_tok->json_ptr = NULL; 32 | jsonp_tok->_next_ptr = parse_str; 33 | jsonp_tok->size = 0; 34 | jsonp_tok->type = JSON_PARSER_STR; 35 | return 1; 36 | } 37 | 38 | void cjsonp_cmd_parser_update(cjsonp_tok_t *jsonp_tok) 39 | { 40 | unsigned long size = 0; 41 | unsigned long i = 0; 42 | if (jsonp_tok->_next_ptr[0] == '[') 43 | { 44 | jsonp_tok->_next_ptr++; 45 | } 46 | jsonp_tok->size = 0; 47 | jsonp_tok->type = JSON_PARSER_STR; 48 | jsonp_tok->json_ptr = NULL; 49 | size = _strlen(jsonp_tok->_next_ptr); 50 | for (i = 0; i < size; i++) 51 | { 52 | if (jsonp_tok->_next_ptr[i] == '.' || jsonp_tok->_next_ptr[i] == '[' || jsonp_tok->_next_ptr[i] == ']') 53 | { 54 | jsonp_tok->size = i; 55 | jsonp_tok->json_ptr = jsonp_tok->_next_ptr; 56 | if (jsonp_tok->_next_ptr[i] == ']') 57 | { 58 | jsonp_tok->type = JSON_PARSER_NUM; 59 | if (jsonp_tok->_next_ptr[i + 1] == '[') 60 | { 61 | jsonp_tok->_next_ptr++; 62 | } 63 | } 64 | else 65 | { 66 | jsonp_tok->type = JSON_PARSER_STR; 67 | } 68 | jsonp_tok->_next_ptr = jsonp_tok->_next_ptr + i + 1; 69 | return; 70 | } 71 | } 72 | if (_strlen(jsonp_tok->_next_ptr) != 0) 73 | { 74 | jsonp_tok->json_ptr = jsonp_tok->_next_ptr; 75 | jsonp_tok->size = _strlen(jsonp_tok->_next_ptr); 76 | jsonp_tok->_next_ptr = ""; 77 | } 78 | } -------------------------------------------------------------------------------- /cjsonp/include/cjsonp.h: -------------------------------------------------------------------------------- 1 | #ifndef CJSONP_H 2 | #define CJSONP_H 3 | 4 | #define CJSONP_DEBUG 1 5 | #include "cJSON.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" 9 | { 10 | #endif 11 | 12 | /** 13 | * @brief 从cjson对象中找到你需要的元素 14 | * 15 | * @param json_root cjson根对象 16 | * @param path 查找cjson的路径 17 | * @return cJSON* 返回的额元素对象 18 | */ 19 | cJSON* cjsonp_search(cJSON* json_root, const char *path); 20 | 21 | /** 22 | * @brief 删除cjson对象的元素 23 | * 24 | * @param json_root cjson根对象 25 | * @param path 删除cjson的路径 26 | * @return int 返回1成功,0失败 27 | */ 28 | int cjsonp_delete(cJSON *json_root, const char *path); 29 | 30 | /** 31 | * @brief 添加cjson元素到对象中 32 | * 33 | * @param json_root cjson根对象 34 | * @param path 添加cjson的路径 35 | * @param add_json 添加的cjson对象 36 | * @return int 返回1成功,0失败 37 | */ 38 | int cjsonp_add(cJSON *json_root, const char *path, cJSON *add_json); 39 | 40 | /** 41 | * @brief 替换cjson对象中的元素 42 | * 43 | * @param json_root cjson根对象 44 | * @param path 替换cjson的路径 45 | * @param rep_json 替换的cjson对象 46 | * @return int 返回1成功,0失败 47 | */ 48 | int cjsonp_replace(cJSON *json_root, const char *path, cJSON *rep_json); 49 | 50 | /** 51 | * @brief 交换json中两个对象 52 | * 53 | * @param json_root cjson根对象 54 | * @param json1_path 交换对象1 55 | * @param json2_path 交换对象2 56 | * @return int 返回1成功,0失败 57 | */ 58 | int cjsonp_swap(cJSON *json_root, const char *json1_path, const char *json2_path); 59 | 60 | #ifdef __cplusplus 61 | } /* extern "C" */ 62 | #endif 63 | 64 | #endif // CJSONP_H 65 | -------------------------------------------------------------------------------- /cjsonp/include/cjsonp_cmd_parser.h: -------------------------------------------------------------------------------- 1 | #ifndef CJSON_CMD_PARSER_H 2 | #define CJSON_CMD_PARSER_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" 6 | { 7 | #endif 8 | 9 | #define JSON_PARSER_STR 0 10 | #define JSON_PARSER_NUM 1 11 | 12 | typedef struct 13 | { 14 | const char *json_ptr; 15 | const char *_next_ptr; 16 | unsigned long size; 17 | char type; 18 | } cjsonp_tok_t; 19 | 20 | char cjsonp_cmd_parser_init(cjsonp_tok_t *jsonp_tok, const char *parse_str); 21 | void cjsonp_cmd_parser_update(cjsonp_tok_t* jsonp_tok); 22 | 23 | #ifdef __cplusplus 24 | } /* extern "C" */ 25 | #endif 26 | 27 | #endif // CJSON_CMD_PARSER_H 28 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | all: build/test.out 2 | 3 | build/test.out: dir build/test.o build/cJSON.o build/cjsonp.o build/cjsonp_cmd_parser.o 4 | gcc -o $@ build/test.o build/cJSON.o build/cjsonp.o build/cjsonp_cmd_parser.o 5 | 6 | dir: 7 | mkdir -p build 8 | 9 | build/test.o: test.c 10 | gcc -o $@ -c $^ -Icjsonp/include -IcJSON 11 | 12 | build/cjsonp.o: cjsonp/cjsonp.c 13 | gcc -o $@ -c $^ -Icjsonp/include -IcJSON 14 | 15 | build/cjsonp_cmd_parser.o: cjsonp/cjsonp_cmd_parser.c 16 | gcc -o $@ -c $^ -Icjsonp/include 17 | 18 | build/cJSON.o: cJSON/cJSON.c 19 | gcc -o $@ -c $^ -IcJSON 20 | 21 | .PHONY: clean run 22 | 23 | run: 24 | ./build/test.out 25 | 26 | clean: 27 | rm -rf build -------------------------------------------------------------------------------- /test.c: -------------------------------------------------------------------------------- 1 | #include "cjsonp.h" 2 | #include 3 | 4 | /* 5 | { 6 | "name":"Awesome 4K", 7 | "resolutions":[ 8 | { 9 | "width":1280, 10 | "height":720 11 | }, 12 | { 13 | "width":1920, 14 | "height":1080 15 | }, 16 | { 17 | "width":3840, 18 | "height":2160 19 | } 20 | ] 21 | } 22 | */ 23 | char json_text[150] = "{\"name\":\"Awesome 4K\",\"resolutions\":[{\"width\":1280,\"height\":720},{\"width\":1920,\"height\":1080},{\"width\":3840,\"height\":2160}]}"; 24 | char* res; 25 | 26 | int main(void) 27 | { 28 | cJSON *json_root = cJSON_Parse(json_text); 29 | 30 | cJSON *json_res = cjsonp_search(json_root, "resolutions[0]width"); 31 | if (json_res != NULL) 32 | { 33 | printf("path: resolutions[0]width \nsearch: %d\n\n", json_res->valueint); 34 | } 35 | 36 | int ret = cjsonp_delete(json_root, "resolutions[0]width"); 37 | if (ret == 1) 38 | { 39 | res = cJSON_Print(json_root); 40 | printf("path: resolutions[0]width \ndelete: %s\n\n", res); 41 | cJSON_free(res); 42 | } 43 | 44 | cJSON *json_add = cJSON_Parse("{\"width\":0, \"height\":0}"); 45 | ret = cjsonp_add(json_root, "resolutions[2]", json_add); 46 | if (ret == 1) 47 | { 48 | res = cJSON_Print(json_root); 49 | printf("path: resolutions[2] \nadd: %s\n\n", res); 50 | cJSON_free(res); 51 | } 52 | 53 | cJSON *json_rep = cJSON_Parse("1200"); 54 | ret = cjsonp_replace(json_root, "resolutions[1]width", json_rep); 55 | if (ret == 1) 56 | { 57 | res = cJSON_Print(json_root); 58 | printf("path: resolutions[1]width \nreplace: %s\n\n", res); 59 | cJSON_free(res); 60 | } 61 | 62 | ret = cjsonp_swap(json_root, "resolutions[1]", "resolutions[2]"); 63 | if (ret == 1) 64 | { 65 | res = cJSON_Print(json_root); 66 | printf("path: resolutions[0]width \nswap: %s\n\n", res); 67 | cJSON_free(res); 68 | } 69 | 70 | cJSON_Delete(json_root); 71 | 72 | return 0; 73 | } --------------------------------------------------------------------------------