c语言操作cJson封装,以及json和结构体互转。如果不做封装直接操作cJSON有点儿繁琐。
所以封装下是很有必要的,使用起来简单好用多了。
这是我计划的终端状态监控服务的终端部分的模块组件。
终端应用程序定时更新状态文件,应用中跑的另一个后台服务则定时读取该状态文件并上送至后台服务。以此无耦合的实现对终端的状态监控。参见:终端出厂后自动化运维方案_独行猫A 的沉淀、积累、总结。天天学习,好好向上...linux,Android,Vue,Go)-CSDN博客
下面是c语言读写json文件的简单封装,完成c语言结构体到json文件,json到结构体的转换。
#include "jsonopt.h" /** * Function:GetArrayValueString * Data:2021-11-11 * Author:yangyongzhen * Description: 从json中获取ArrayItem内容 */ int GetArrayValueString(cJSON* json,int id, char* name, char* param){ cJSON* node; node = cJSON_GetArrayItem(json,id); if(!node){ return -1; } sprintf(param, "%s", cJSON_GetObjectItem(node, name)->valuestring); return 0 ; } /** * Function:GetValueString * Data:2021-11-11 * Author:yangyongzhen * Description: 从json中读取字符串内容 */ char* GetValueString(cJSON* json,char* name){ cJSON* pObj = NULL; pObj = cJSON_GetObjectItem(json,name); if(pObj != NULL){ return pObj->valuestring; }else{ return NULL; } } /** * Function:GetValueInt * Data:2021-11-11 * Author:yangyongzhen * Description: 从json中读取int类型值 */ int GetValueInt(cJSON* json,char* name){ cJSON* pObj = NULL; pObj = cJSON_GetObjectItem(json,name); if(pObj != NULL){ return pObj->valueint; }else{ return 0; } } /** * Function:SetValueString * Data:2021-11-11 * Author:yangyongzhen * Description: 向json中的String类型字段赋值 */ int SetValueString(cJSON* json,char* name,char* value){ //printf("set key:%s,val:%s\n",name,value); if(cJSON_GetObjectItem(json,name)->valuestring != NULL){ cJSON_ReplaceItemInObject(json,name,cJSON_CreateString(value)); }else{ //cJSON_AddItemToObject(json, name, cJSON_CreateString(value)); cJSON_AddStringToObject(json, name, value); } return 0; } /** * Function:SetValueInt * Data:2021-11-11 * Author:yangyongzhen * Description: 向json中的Int类型字段赋值 */ int SetValueInt(cJSON* json,char* name,int value){ cJSON* pObj = NULL; pObj = cJSON_GetObjectItem(json,name); if(pObj != NULL){ pObj->valueint = value; pObj->valuedouble = value; return 0; }else{ cJSON_AddNumberToObject(json, name, value); } return 0; }
/** * Copyright (C), 2021-2021,yangyongzhen * File name: jsonopt.h * Author: yangyongzhen * Version: 0.1 * Date: 2021-11-11 * Description: c语言的cJSON操作封装 **/ #ifndef _JSON_OPT_H_ #define _JSON_OPT_H_ #include <string.h> #include "cJSON.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /** * Function:S2J_setInt * Description:Struct向Json的Int类型赋值 * */ #define S2J_setInt(json,stru,element) SetValueInt(json,#element,(stru)->element) /** * Function:S2J_setString * Description:Struct向Json的String类型赋值 * */ #define S2J_setString(json,stru,element) SetValueString(json,#element,(stru)->element) /** * Function:J2S_getString * Description:Json向Struct中的String类型赋值 * */ #define J2S_getString(json,stru,element) {char *item=NULL; item = GetValueString(json,#element); if(item!=NULL){strcpy((stru)->element,item);}} /** * Function:J2S_getInt * Description:Json向Struct中的Int类型赋值 * */ #define J2S_getInt(json,stru,element) (stru)->element = GetValueInt(json,#element) /** * Function:GetArrayValueString * Data:2021-11-11 * Author:yangyongzhen * Description: 从json中获取ArrayItem内容 */ extern int GetArrayValueString(cJSON* json,int id, char* name, char* param); /** * Function:GetValueString * Data:2021-11-11 * Author:yangyongzhen * Description: 从json中读取字符串内容 */ extern char* GetValueString(cJSON* json,char* name); /** * Function:GetValueInt * Data:2021-11-11 * Author:yangyongzhen * Description: 从json中读取int类型值 */ extern int GetValueInt(cJSON* json,char* name); /** * Function:SetValueString * Data:2021-11-11 * Author:yangyongzhen * Description: 向json中的String类型字段赋值 */ extern int SetValueString(cJSON* json,char* name,char* value); /** * Function:SetValueInt * Data:2021-11-11 * Author:yangyongzhen * Description: 向json中的Int类型字段赋值 */ extern int SetValueInt(cJSON* json,char* name,int value); #ifdef __cplusplus } #endif /* __cplusplus */ #endif
使用方法举例:
#include "jsonopt.h" static cJSON* root; PosStatus posStatus; /** 从json文件中加载信息到结构体 */ int LoadStatus(PosStatus *status){ printf("LoadStatus ENTER\n"); root = GetJsonObject(STATUS_FILE_NAME); char * out = cJSON_Print(root); printf("LoadStatus:json=%s\n",out); if(out == NULL){ printf("LoadStatus error,no json data\n"); return -1; } J2S_getString(root,status,sn); printf("[item] = %s\n",status->sn); J2S_getString(root,status,posno); printf("[item] = %s\n",status->posno); J2S_getString(root,status,city); printf("[item] = %s\n",status->city); J2S_getString(root,status,tyid); printf("[item] = %s\n",status->tyid); J2S_getString(root,status,sver); printf("[item] = %s\n",status->sver); J2S_getString(root,status,ctime); printf("[item] = %s\n",status->ctime); //item = GetValueString(root,"posno"); //if(item != NULL){ // strcpy(status->posno,item); // printf("[item] = %s\n",status->posno); //} return 0; } /** 结构体信息保存为json文件 */ int SaveStatus(PosStatus status){ char * out = NULL; printf("SaveStatus ENTER\n"); if(root == NULL){ printf("SaveStatus error\n"); return -1; } S2J_setString(root,&status,sn); S2J_setString(root,&status,posno); S2J_setString(root,&status,tyid); S2J_setString(root,&status,city); S2J_setString(root,&status,sver); S2J_setInt(root,&status,unum1); S2J_setInt(root,&status,unum2); S2J_setInt(root,&status,amount); S2J_setInt(root,&status,count); S2J_setInt(root,&status,line); S2J_setString(root,&status,carno); S2J_setString(root,&status,jd); S2J_setString(root,&status,wd); S2J_setInt(root,&status,alarm); S2J_setInt(root,&status,pver); S2J_setInt(root,&status,bver); S2J_setString(root,&status,empid); S2J_setString(root,&status,rvs1); S2J_setString(root,&status,rvs2); S2J_setString(root,&status,stime); S2J_setString(root,&status,ctime); S2J_setInt(root,&status,tenant); //SetValueString(root,"carno",status.carno); //SetValueString(root,"jd",status.jd); //SetValueString(root,"wd",status.wd); printf("SaveStatus end\n"); out = cJSON_Print(root); writeFile(STATUS_FILE_NAME,out); printf("SetStatus:json=%s\n",out); return 0; }
//status.h头文件 #ifndef _STATUS_H_ #define _STATUS_H_ #include "cJSON/cJSON.h" //保存位置 终端状态监控文件存储位置 #define STATUS_FILE_NAME "../opt/status.json" //#define STATUS_FILE_NAME "./status.json" //终端设备状态信息 typedef struct _PosStatus{ char sn[32]; //设备唯一号 char posno[16]; //终端编号 char city[10]; //城市代码 char tyid[10]; //终端类型 char sver[32]; //终端版本号 int unum1; //未传记录数量--公交 int unum2; //未传记录数量--三方 char ndate[16]; //当前日期 char ntime[16]; //当前时间 int amount; //当班总额 int count; //当班人数 int line; //线路号 char carno[16]; //车辆编号 char jd[20]; //经度 char wd[20]; //维度 int alarm; //设备报警码 char stime[16]; //开机时间 char ctime[16]; //关机时间 int tenant; //租户ID }PosStatus; extern PosStatus posStatus; extern int LoadStatus(PosStatus *status); extern int SaveStatus(PosStatus status); extern int SetValueInt(cJSON* root,char* name,int value); extern int SetValueString(cJSON* root,char* name,char* value); extern char* GetValueString(cJSON* json,char* name); extern int GetValueInt(cJSON* json,char* name); extern cJSON* GetJsonObject(char* fileName); extern int writeFile(char *filename,char *data); #endif
static.c文件内容:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "status.h" static cJSON* root; PosStatus posStatus; /** 从文件中读取json信息到结构体 */ int LoadStatus(PosStatus *status){ root = GetJsonObject(STATUS_FILE_NAME); char * out = cJSON_Print(root); printf("LoadStatus:json=%s\n",out); if(out == NULL){ printf("LoadStatus error,no json data\n"); return -1; } char * item = NULL; item = GetValueString(root,"sn"); if(item != NULL){ strcpy(status->sn,item); printf("[item] = %s\n",status->sn); } item = GetValueString(root,"posno"); if(item != NULL){ strcpy(status->posno,item); printf("[item] = %s\n",status->posno); } item = GetValueString(root,"city"); if(item != NULL){ strcpy(status->city,item); printf("[item] = %s\n",status->city); } item = GetValueString(root,"tyid"); if(item != NULL){ strcpy(status->tyid,item); printf("[item] = %s\n",status->tyid); } item = GetValueString(root,"sver"); if(item != NULL){ strcpy(status->sver,item); printf("[item] = %s\n",status->sver); } return 0; } /** 结构体信息写入json文件 */ int SaveStatus(PosStatus status){ char * out = NULL; printf("SaveStatus ENTER\n"); if(root == NULL){ printf("SaveStatus error\n"); return -1; } SetValueString(root,"sn",status.sn); SetValueString(root,"posno",status.posno); SetValueString(root,"tyid",status.tyid); SetValueString(root,"city",status.city); SetValueString(root,"sver",status.sver); SetValueInt(root,"unum1",status.unum1); SetValueInt(root,"unum2",status.unum2); SetValueInt(root,"amount",status.amount); SetValueInt(root,"count",status.count); SetValueInt(root,"line",status.line); SetValueString(root,"carno",status.carno); SetValueString(root,"jd",status.jd); SetValueString(root,"wd",status.wd); SetValueInt(root,"alarm",status.alarm); SetValueString(root,"stime",status.stime); SetValueString(root,"ctime",status.ctime); SetValueInt(root,"tenant",status.tenant); out = cJSON_Print(root); writeFile(STATUS_FILE_NAME,out); printf("SetStatus:json=%s\n",out); return 0; } int writeFile(char *filename,char *data){ FILE *fp = NULL; fp = fopen(filename,"w+"); if(fp == NULL){ fprintf(stderr,"open file failed\n"); return -1; } fprintf(fp,"%s",data); if(fp != NULL){ fclose(fp); } return 0; } cJSON* GetJsonObject(char* fileName){ long len; char* pContent; int tmp; cJSON* json; FILE* fp = fopen(fileName, "rb+"); if(!fp){ printf("open file error\n"); return NULL; } printf("open file success\n"); fseek(fp,0,SEEK_END); len=ftell(fp); if(0 == len){ printf("file len is 0\n"); return NULL; } fseek(fp,0,SEEK_SET); pContent = (char*) malloc (sizeof(char)*len); tmp = fread(pContent,1,len,fp); fclose(fp); json = cJSON_Parse(pContent); if (!json) { free(pContent); return NULL; } free(pContent); printf("read file ok\n"); return json; } //读取cJSON索引为index的结点某个key值对应的value,索引从0开始 int GetArrayValueString(cJSON* json,int id, char* name, char* param){ cJSON* node; node = cJSON_GetArrayItem(json,id); if(!node){ return -1; } sprintf(param, "%s", cJSON_GetObjectItem(node, name)->valuestring); return 0 ; } char* GetValueString(cJSON* json,char* name){ cJSON* pObj = NULL; pObj = cJSON_GetObjectItem(json,name); if(pObj != NULL){ return pObj->valuestring; }else{ return NULL; } } int GetValueInt(cJSON* json,char* name){ cJSON* pObj = NULL; pObj = cJSON_GetObjectItem(json,name); if(pObj != NULL){ return pObj->valueint; }else{ return 0; } } int SetValueString(cJSON* json,char* name,char* value){ strcpy(cJSON_GetObjectItem(json,name)->valuestring,value); return 0; } int SetValueInt(cJSON* json,char* name,int value){ cJSON_GetObjectItem(json,name)->valueint = value; cJSON_GetObjectItem(json,name)->valuedouble = value; return 0; } /* int main(){ printf("cjson test,read and save\n"); LoadStatus(&posStatus); strcpy(posStatus.sver,"NC_B503_YYZ"); posStatus.alarm = 6; posStatus.amount = 10; posStatus.count = 12; strcpy(posStatus.posno,"413101010E"); SaveStatus(posStatus); } */
生成的json文件如:
{ "sn": "00a0c6000023", "posno":"413101010E", "city": "", "tyid": "", "sver": "NC_B503_YYZ", "unum1": 0, "unum2": 0, "ndate": "2021-08-11", "ntime": "17:20:30", "amount": 10, "count": 12, "line": 0, "carno": "", "jd": "", "wd": "", "alarm": 6, "stime": "", "ctime": "", "tenant": 0 }
附带一个终端开机自启动脚本startmonitor.sh:
#!/bin/bash fileName="/app/city_app/opt/monitor" buzzGPIO="/sys/class/gpio/gpio15" #enable buzzse for notifying success function beep_notify() { if [ ! -d "$buzzGPIO" ]; then echo 15 > /sys/class/gpio/export fi if [ -d "$buzzGPIO" ]; then echo "out" > "/sys/class/gpio/gpio15/direction" echo "1" > "/sys/class/gpio/gpio15/value" sleep 1 echo "0" > "/sys/class/gpio/gpio15/value" fi } function CheckProcess() { PROCESS_NUM=`ps | grep "$1" | grep -v "grep" | wc -l` return $PROCESS_NUM } if [ ! -f $fileName ]; then echo "error!monitor file not exit!" exit 1 else echo "find monitor file,begin start..." CheckProcess qrlinux if [ $? -eq 0 ];then echo "no monitor progress find!" else echo "find monitor,..." killall -9 monitor sleep 1 fi cd /app/city_app/opt/ ./monitor -monitorcfg=./monitorcfg.ini & echo "start ok" beep_notify exit 0 fi
终端开机自启动服务应用的方法:
system("killall -9 monitor"); system("../opt/startmonitor.sh");