├── .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 | }
--------------------------------------------------------------------------------