还是在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
#include
#include
#include
#include
#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;
}