还是在Linux下,使用C语言编程,先实现写文件的功能,然后开始josn字符串的创建。我们还是一步步来,先从简单的开始。
首先是一个简单的键值对字符串,要生成的目标如下:
{"firstName":"Brett"}
相比于解析,此时是创建,依据键值的定义(firstName)以及初始值(Brett),需要生成符合Json标准的字符串。
此时,我们是先有结构体,后来实现Json中的对象。结构体如下:
typedef struct
{
char firstName[32];
char lastName[32];
char email[64];
int age;
float height;
}people;
对于结构体中的每一个成员,先要定义好key,然后取值转换为相应字符串。
在这里,我们需要判断这个结构体的最后一个成员的处理,即在最后一个键值对之后,应该是“,”还是“}”,需要能区分清楚。
由于前面已经实现了从结构体创建Json串,此时只需要添加数组的架构,并多次进行结构体的创建即可。
此时,Json串的内容已经比较多了,如何没有换行,则长长的一行,会让人看得迷迷糊糊的,可读性不好。我们可以调整下格式,让Json串变得更有条理一些:既然已知是结构体数组,那么,分层结构也是比较清晰的,即内部是结构体,再外层是数组。考虑到结构体内容并不多,可以简单的将每个结构体的内容展示在一行中,而对于数组的形式也增加一个换行,格式如下,这样就清晰多了:
{
"people":[
{"firstName":"z","lastName":"Jason","email":"[email protected]","height":1.67},
{"lastName":"jadena","email":"[email protected]","age":8,"height":1.17},
{"email":"[email protected]","firstName":"z","lastName":"Juliet","age":36,"height":1.55}
]
}
当然,还可以调整得更好,例如每行只存储一个键值对,每行有缩进,缩进的宽度,又与所处层次有关,不过那就是下一步的事情了,呵呵。
若存在结构体中包含数组,数组中包含结构体,多层嵌套,如何创建Json串?
不管多复杂的嵌套结构,只要明确下来了,然后就可以定义一个协议,即键值对的定义,然后逐层转换即可。
从这里的分析,对比之前做解析时的分析,就可以知道,其实创建Json串比解析要简单!创建json格式时,不用考虑那么多异常情况的处理,只是按照一种符合标准的写法实现出来即可。当然,这里的简单,是说逻辑上,以及代码实现上简单。这种实现方案,还是按照定制的消息接口协议进行的,实现代码与协议密切相关,没有将Json规则独立出来。
如果要将Json规则独立出来,以实现Json字符串的创建的统一接口,那么,结构体与数组的嵌套,必然是需要递归调用才能实现的,这种逻辑也是比较复杂的了。
本文所附带例程,只是一个学习之作,对于初学Json的同学,可以有些借鉴参考的作用。但是,对于异常处理、字符串中的特殊字符的处理等,都不完善,创建Json字符串的方法也不是一个通用的接口,只能根据具体的协议,来定制相应的创建函数,在使用时要求编程者对Json格式非常了解,所以,并不是很适用于软件工程开发中。
真正用于软件工程开发中的Json接口,C语言版本的大家可以参考CJSON,下载地址为http://sourceforge.net/projects/cjson/。至于其他语言的,可以到http://www.json.org.cn/ 中去寻找相应的实现。
#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #define PRINT(msg...) do {printf("lintax: "); printf(msg);}while(0) typedef struct { int id; char firstName[32]; char lastName[32]; char email[64]; int age; float height; }people; //create json string int produce_str_value_in_json(char * json_str, int str_len, char * str_key, char * str_value) { int pos_str=0; if ( (json_str==NULL)||(str_key==NULL)||(str_value==NULL)) { PRINT("input str is NULL\n"); return -1; } if(str_len<=0) { PRINT("input param is invalid: str_len=%d\n",str_len); return -1; } if(str_key[0]==0) { PRINT("input key is invalid\n"); return -1; } //str_len, is overflow ? int len_add=strlen(str_key)+strlen(str_value)+5; //PRINT("%s:str_len=%d, len_add=%d\n",__func__,str_len,len_add); if(len_add>=str_len) { PRINT("error: input str len is too small: str_len=%d\n",str_len); return -1; } sprintf(json_str+pos_str, "\"%s\":\"%s\"",str_key,str_value); PRINT("%s,json_str:%s\n",__func__,json_str); return len_add; } int produce_int_value_in_json(char * json_str, int str_len, char * str_key, int value) { int pos_str=0; if ( (json_str==NULL)||(str_key==NULL)) { PRINT("input str is NULL\n"); return -1; } if(str_len<=0) { PRINT("input param is invalid: str_len=%d\n",str_len); return -1; } if(str_key[0]==0) { PRINT("input key is invalid\n"); return -1; } //str_len, is overflow ? char str_add[128]={0}; int len_add=0; sprintf(str_add, "\"%s\":%d",str_key,value); len_add=strlen(str_add); //PRINT("%s:str_len=%d, len_add=%d\n",__func__,str_len,len_add); if(len_add>=str_len) { PRINT("error: input str len is too small: str_len=%d\n",str_len); return -1; } sprintf(json_str+pos_str, "%s",str_add); PRINT("%s,json_str:%s\n",__func__,json_str); return len_add; } int produce_float_value_in_json(char * json_str, int str_len, char * str_key, float value) { int pos_str=0; if ( (json_str==NULL)||(str_key==NULL)) { PRINT("input str is NULL\n"); return -1; } if(str_len<=0) { PRINT("input param is invalid: str_len=%d\n",str_len); return -1; } if(str_key[0]==0) { PRINT("input key is invalid\n"); return -1; } //str_len, is overflow ? char str_add[128]={0}; int len_add=0; sprintf(str_add, "\"%s\":%.02f",str_key,value); len_add=strlen(str_add); //PRINT("%s:str_len=%d, len_add=%d\n",__func__,str_len,len_add); if(len_add>=str_len) { PRINT("error: input str len is too small: str_len=%d\n",str_len); return -1; } sprintf(json_str+pos_str, "%s",str_add); PRINT("%s,json_str:%s\n",__func__,json_str); return len_add; } int main(int argc, char **argv) { int ret=-1, i; char str_create[4096]={0};//, buf[BUFSIZE], int len_str_create=0; int pos,pos_str=0; FILE *fp; char file_path[100]; people workers[10]={ {0,"z","Jason","[email protected]",0,1.67}, {1,"","jadena","[email protected]",8,1.17}, {2,"z","Juliet","[email protected]",36,1.55} }; //create json string printf("\nto create json string:\n"); int str_len=sizeof(str_create); pos_str=0; if ( str_create==NULL) { return -1; } sprintf(str_create+pos_str, "{");//the json string start pos_str++; char str_add[128]={0}; int len_add=0; sprintf(str_add, "\"people\":[\n");//the array start len_add=strlen(str_add); sprintf(str_create+pos_str, "%s",str_add); pos_str+=len_add; for(i=0;i<3;i++) { if(i>0) { sprintf(str_create+pos_str, ",\n");//between two structs pos_str+=2; } sprintf(str_create+pos_str, "{");//the struct start pos_str++; pos=produce_str_value_in_json(str_create+pos_str, str_len-pos_str, "firstName", workers[i].firstName); //PRINT("produce_str_value_in_json firstName pos=%d\n",pos); if(pos<0) { PRINT("produce_str_value_in_json ret failed\n"); return -1; } pos_str+=pos; sprintf(str_create+pos_str, ",");//between two struct members pos_str++; pos=produce_str_value_in_json(str_create+pos_str, str_len-pos_str, "lastName", workers[i].lastName); //PRINT("produce_str_value_in_json lastName pos=%d\n",pos); if(pos<0) { PRINT("produce_str_value_in_json ret failed\n"); return -1; } pos_str+=pos; sprintf(str_create+pos_str, ",");//between two struct members pos_str++; pos=produce_str_value_in_json(str_create+pos_str, str_len-pos_str, "email", workers[i].email); //PRINT("produce_str_value_in_json email pos=%d\n",pos); if(pos<0) { PRINT("produce_str_value_in_json ret failed\n"); return -1; } pos_str+=pos; sprintf(str_create+pos_str, ",");//between two struct members pos_str++; pos=produce_int_value_in_json(str_create+pos_str, str_len-pos_str, "age", workers[i].age); //PRINT("produce_str_value_in_json age pos=%d\n",pos); if(pos<0) { PRINT("produce_str_value_in_json ret failed\n"); return -1; } pos_str+=pos; sprintf(str_create+pos_str, ",");//between two struct members pos_str++; pos=produce_float_value_in_json(str_create+pos_str, str_len-pos_str, "height", workers[i].height); //PRINT("produce_str_value_in_json height pos=%d\n",pos); if(pos<0) { PRINT("produce_str_value_in_json ret failed\n"); return -1; } pos_str+=pos; sprintf(str_create+pos_str, "}");//the struct end pos_str++; } sprintf(str_create+pos_str, "\n]");//the array end pos_str+=2; sprintf(str_create+pos_str, "}");//the json string end pos_str++; len_str_create=pos_str; if(len_str_create<0) { PRINT("create_json_str ret failed\n"); return -1; } else { PRINT("create_json_str ret %s\n",str_create); } //write file sprintf(file_path,"json_str_create.txt"); fp = fopen(file_path, "w"); if (NULL == fp) { printf("open file %s fail : %m.\n", file_path); return ret; } ret=fwrite(str_create,len_str_create,1,fp); /* 一次性读取全部文件内�?*/ /**/ fclose(fp); return 0; }