[app] 试一下ulysses
这篇文章主要目的是为了试试Ulysses在这个github.io上好不好用。至于写的东西嘛,就写写今天刚研究的cJSON的东西吧——就算是凑字数了。 至于CS:APP第四章,我看到之前的计划里没列这个,设计处理器离我也的确比较遥远;所以,第四章就先跳过去,之后从第五章接着看,讲的是程序优化,似乎非常有用。 好了,下面记录一下cJSON。
cJSON简介
简单来说就是用纯C语言写的处理JSON文档的库,使用起来挺方便的,可以直接将cJSON.c和cJSON.h文件复制到自己的项目代码中使用,其许可证也是对商业友好的。 链接:cJSON Github
关于例程
在网上找了cJSON的使用说明。其实最好的说明就是Github上的readme.mk了,不过别人的博客写的会更为直接点。 我参考的是Rotation.的一篇博客,然后也自己试了试人家写的程序,并做了一点说明。 对这篇博客一些内容,有几点我不赞同或者没有说明白:
- 我认为编译JSON不用链接math库
- s = cJSON_Parse(cJSON);在s使用完后,必须free(s);
- 对于整个JSON信息,只需对root进行删除操作。
- 删除操作cJSON_Delete(NULL)是安全的。
- 对于json数组里又是JSON对象,作者说要把这个项先转为普通字符串,再转为json对象。我不这么认为,虽然我也没测试,我想不用再经过字符串,可以直接当做json对象解析。
例程1
创建JSON,并添加一些信息。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
int main(int argc, char *argv[])
{
cJSON *user = NULL;
char *out = NULL;
user = cJSON_CreateObject();
cJSON_AddStringToObject(user, "name", "aningsk");
cJSON_AddStringToObject(user, "passwd", "123456");
cJSON_AddNumberToObject(user, "number", 1);
out = cJSON_Print(user);
printf("%s\n", out);
free(out); // After use @out, I think it's necessary to free it.
cJSON_Delete(user);
return 0;
}
这里需要注意的是:
- 使用cJSON_Print()后,需要对那个指针使用free()。
例程2
创建JSON数组,数组里一个字符串、一个数字。
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
int create_js(void)
{
cJSON *root = NULL;
cJSON *js_body = NULL;
char *string = NULL;
root = cJSON_CreateArray();
if (NULL == root) {
printf("Error: create root\n");
return -1;
}
cJSON_AddItemToArray(root, cJSON_CreateString("Hello world"));
cJSON_AddItemToArray(root, cJSON_CreateNumber(10));
string = cJSON_PrintUnformatted(root);
if (NULL != string) {
printf("%s\n", string);
free(string);
}
cJSON_Delete(root);
return 0;
}
int main(int argc, char *argv[])
{
return create_js();
}
例程3
创建JSON,添加数组
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
int create_js(void)
{
int ret = 0;
cJSON *root = NULL;
cJSON *js_body = NULL;
cJSON *js_list1 = NULL;
cJSON *js_list2 = NULL;
char *string = NULL;
root = cJSON_CreateObject();
if (NULL == root) {
printf("Error: create root\n");
ret = -1;
/*
* In fact, cJSON_Delete(NULL) is safe,
* so here we can just
* goto end;
* not need anthor label such as "fail".
*/
goto fail;
}
js_body = cJSON_CreateArray();
if (NULL == js_body) {
printf("Error: create js_body\n");
ret = -1;
goto end;
}
js_list1 = cJSON_CreateObject();
if (NULL == js_list1) {
printf("Error: create js_list1\n");
ret = -1;
goto end;
}
js_list2 = cJSON_CreateObject();
if (NULL == js_list2) {
printf("Error: create js_list2\n");
ret = -1;
goto end;
}
cJSON_AddItemToObject(root, "body", js_body);
cJSON_AddItemToArray(js_body, js_list1);
cJSON_AddItemToArray(js_body, js_list2);
cJSON_AddStringToObject(js_list1, "name", "aningsk");
cJSON_AddNumberToObject(js_list1, "status", 100);
cJSON_AddStringToObject(js_list2, "name", "nikos");
cJSON_AddNumberToObject(js_list2, "status", 100);
string = cJSON_Print(root);
if (NULL != string) {
printf("%s\n", string);
free(string);
}
end:
/*
* Because all others object/array had been added into @root,
* we just need to delete @root, and others would also be
* deleted together; not need to delete them manually again.
*/
cJSON_Delete(root);
fail:
return ret;
}
int main(int argc, char *argv[])
{
return create_js();
}
需要说明的是:
- cJSON_Delete(NULL)是安全的,所以可以不用像上文代码中多一个“fail”标签。
- 另外,所有的对象都加入到同一个root节点,在最后释放时,只释放root就可以了。
例程4
从JSON中解析信息
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
int main(int argc, char *argv[])
{
char *out = "{\"name\":\"aningsk\",\"passwd\":\"123456\",\"number\":1}";
cJSON *json = NULL;
cJSON *json_name = NULL;
cJSON *json_passwd = NULL;
cJSON *json_number = NULL;
json = cJSON_Parse(out);
//#define CASE_SENSITIVE
#ifdef CASE_SENSITIVE
json_name = cJSON_GetObjectItemCaseSensitive(json, "name");
json_passwd = cJSON_GetObjectItemCaseSensitive(json, "passwd");
json_number = cJSON_GetObjectItemCaseSensitive(json, "number");
#else
json_name = cJSON_GetObjectItem(json, "Name");
json_passwd = cJSON_GetObjectItem(json, "Passwd");
json_number = cJSON_GetObjectItem(json, "Number");
#endif /* CASE_SENSITIVE */
printf("We get:\n\tname:%s\n\tpasswd:%s\n\tnumber:%d\n",
json_name->valuestring,
json_passwd->valuestring,
json_number->valueint);
cJSON_Delete(json);
return 0;
}
要注意的是:
- 使用cJSON_Parse()后,也要记得对应使用cJSON_Delete()。
- cJSON_GetObjectItem()是忽略字母大小写的,同时也有不忽视大小写的。
例程5
从JSON中解析信息,以及从JSON中的JSON(一个“list”、一个“other”)解析信息。
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
int main(int argc, char *argv[])
{
int ret = 0;
char *info =
"{\"list\":{\"name\":\"aningsk\",\"age\":10},\"other\":{\"name\":\"nikos\"}}";
cJSON *root = NULL;
cJSON *js_list = NULL;
cJSON *name = NULL;
cJSON *age = NULL;
cJSON *js_other = NULL;
cJSON *js_name = NULL;
char *string = NULL;
root = cJSON_Parse(info);
if (NULL == root) {
printf("Error: Parse root\n");
ret = -1;
goto end;
}
string = cJSON_Print(root);
if (NULL != string) {
printf("Original info:\n%s\n", string);
free(string);
}
js_list = cJSON_GetObjectItem(root, "list");
if (NULL == js_list) {
printf("Error: get list\n");
ret = -1;
goto end;
}
printf("list type is %d\n", js_list->type);
name = cJSON_GetObjectItem(js_list, "name");
if (NULL == name) {
printf("Error: get name\n");
ret = -1;
goto end;
}
printf("name type is %d\n", name->type);
printf("name is %s\n", name->valuestring);
age = cJSON_GetObjectItem(js_list, "age");
if (NULL == age) {
printf("Error: get age\n");
ret = -1;
goto end;
}
printf("age type is %d\n", age->type);
printf("age is %d\n", age->valueint);
printf("age also is %f\n", age->valuedouble);
js_other = cJSON_GetObjectItem(root, "other");
if (NULL == js_other) {
printf("Error: get other\n");
ret = -1;
goto end;
}
printf("other type is %d\n", js_other->type);
js_name = cJSON_GetObjectItem(js_other, "name");
if (NULL == js_name) {
printf("Error: get name\n");
ret = -1;
goto end;
}
printf("name type is %d\n", js_name->type);
printf("name is %s\n", js_name->valuestring);
printf("\n");
printf("cJSON_Invalid = %d\n", cJSON_Invalid);
printf("cJSON_False = %d\n", cJSON_False);
printf("cJSON_True = %d\n", cJSON_True);
printf("cJSON_NULL = %d\n", cJSON_NULL);
printf("cJSON_Number = %d\n", cJSON_Number);
printf("cJSON_String = %d\n", cJSON_String);
printf("cJSON_Array = %d\n", cJSON_Array);
printf("cJSON_Object = %d\n", cJSON_Object);
printf("cJSON_Raw = %d\n", cJSON_Raw);
end:
cJSON_Delete(root);
return ret;
}
注意的问题:
- 一般来说,从cJSON对象获得值,要先判断一下type。
例程6
从JSON数组中解析信息
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
int main(int argc, char *argv[])
{
int ret = 0;
char *string = "{\"list\":[\"name-1\",\"name-2\"]}";
cJSON *root = NULL;
cJSON *list = NULL;
cJSON *item = NULL;
char *info = NULL;
int array_size = 0;
int i = 0;
root = cJSON_Parse(string);
if (NULL == root) {
printf("Error: parse root\n");
ret = -1;
goto end;
}
info = cJSON_Print(root);
if (NULL == info) {
printf("Original info:\n%s\n", info);
free(info);
}
list = cJSON_GetObjectItem(root, "list");
if (NULL == list) {
printf("Error: get list\n");
goto end;
}
array_size = cJSON_GetArraySize(list);
printf("array size is %d\n", array_size);
for (i = 0; i < array_size; i++) {
item = cJSON_GetArrayItem(list, i);
printf("item type is %d\n", item->type);
printf("item value: %s\n", item->valuestring);
}
end:
cJSON_Delete(root);
return ret;
}
好像没什么要太注意的。就是一层一层的解析呗。
嗯嗯,就先写到这里了。
Written on May 12, 2020