cJSON的使用介绍及实例分析

使用意图:
用于方便实现包含充电信息的结构体输入到文件中,然后需要的时候,从文件中以充电信息的结构体的形式输出;

简要介绍:
cJSON的使用,网上有很多的资料,主要就是两个文件,一个头文件cJSON.h,一个应用文件cJSON.c,前者主要是对cJSON.c的一些函数的声明,我们在自己的应用程序中,比如main.c中,包含cJSON.h,以及在编译的时候,将cJSON.c和main.c一起编译,即:

gcc main.c cJSON.c -g -lm -o main

这里我用的是:

gcc cJSON.c test.c bx_deal.c -g -lm -o bx_deal

注:test.c中写入的main函数(c语言编译入口),其中用到的cJSON的应用函数都在bx_deal.c中,而bx_deal.c中的函数中用到的cJSON函数都在cJSON.c中,这样做的目的是,用bx_deal.c作为中间文件,能够在其中传参的时候,根据我们的需求以及实际使用,更具灵活性,像这里,几个函数:
SK_API int bx_deal_init(const char *p_fileName);

/// @brief 模块反初始化
SK_API int bx_deal_quit();

/// @brief 按下标读取一条信息
/// @param [in] seq: 序号
/// @param [out] p_dealInfo: 保存交易记录的结构体
/// @return 0:成功 非0:失败
/// 将结果存到一个结构体中,即*p_dealInfo;
SK_API int bx_read_dealInfo(unsigned short seq,deal_info_t *p_dealInfo);

/// @brief 按下标读取一条信息
/// @param [in] seq: 序号
/// @param [in] p_dealInfo: 交易记录的结构体
/// @return 0:成功 非0:失败

SK_API int bx_write_dealInfo(deal_info_t *p_dealInfo);

/// @brief 获取最新的交易记录下标
/// @return 最新的交易记录下标
SK_API unsigned short bx_get_max_index();

这几个函数方便我们处理自己传递的数据信息(这里主要是以将充电信息以结构体的信息输出),最后实现的就是将我们的充电信息(结构体,在文件中pub_type.h有定义),从传进来的结构体读入文件中,然后在需要显示的时候,从文件提取出来,或者读出来;

程序源码分析:
程序梳理:
所有程序
这里主要是由:
cJSON的接口函数文件 - cJSON.c和cJSON.h;
主要包含充电信息结构体的头文件 - pub_type.h
cJSON的使用介绍及实例分析_第1张图片
主要包含充电信息结构体等的头文件baoxin_def.h:
cJSON的使用介绍及实例分析_第2张图片
test.c就是我们的头文件,里面写好了main函数,使用bx_deal.c中的一些用户函数,然后这些用户函数又套用了cJSON.c中的一些头文件;
所以我们在编译的时候需要:

gcc test.c cJSON.c bx_deal.c -g -lm -o bx_deal

注:会生成一个文本文件,chargeinfo.txt;

程序联系:
test.c中用了bx_deal.c中的函数,bx_deal.c中又套用了cJSON.c中的函数;
test.c中用到了baoxin_def.h中充电信息结构体,而这个结构体中用到了pub_type.h的SK_TIME结构体成员;
bx_deal.h和CJSON.h分别是bx_deal.c和CJSON.c里面是对他们的头文件中的函数的声明;
chargeinfo.txt是这个程序运行生成的;

程序分析:
下面给出除了cJSON.h和cJSON.c以外的头文件,这两个文件可以在网上找到,给出了bx_deal.c,bx_deal.h,test.c,pub_type.h,baoxin_def.h等五个文件,共七个文件;以及编译,运行程序生成的文本文件chargeinfo.txt;

bx_deal.c文件:

#include "baoxin_def.h"
#include "bx_deal.h"
#include 
#include "cJSON.h"
#include 
#include 
#include 

//const  char *g_dealFile  = "usr/data/deal.json";
//const char *g_dealFile = "/mnt/hgfs/share_for_linux/cJSON_lib_use/chargeinfo.txt";


const char START_TIME[] =   "start_time";
const char STOP_TIME[]  =   "stop_time";
const char CHARGE_TIME[]    =   "charge_time";
const char TOTAL_KWH[]  =   "total_kwh";
const char SEQ[]        =   "seq";

typedef struct bx_dealInfo_t 
{
    char *          p_text;
    cJSON *         p_deal;

    int             buf_len;
    int             max_num;

    char                path[128];
}bx_dealInfo_t;



const int MAX_BUF_SIZE = 16 * 1024;
const int MAX_DEAL_NUM   = 100;
static bx_dealInfo_t *g_p_dealInfo = NULL;



static void event_write()
{
    assert(NULL != g_p_dealInfo->p_text);

    //
    while (g_p_dealInfo->buf_len < strlen(g_p_dealInfo->p_text))
    {
        free(g_p_dealInfo->p_text);
        g_p_dealInfo->p_text = NULL;

        //删除最老的记录
        int count = cJSON_GetArraySize(g_p_dealInfo->p_deal);
        if (g_p_dealInfo->max_num < count)
            cJSON_DeleteItemFromArray(g_p_dealInfo->p_deal, count - 1);

        g_p_dealInfo->p_text = cJSON_PrintUnformatted(g_p_dealInfo->p_deal);
    }

    assert(NULL != g_p_dealInfo->p_text);

    //刷新到文件
    FILE *p_file = fopen(g_p_dealInfo->path, "w");
    assert(NULL != p_file);

    int len = fwrite(g_p_dealInfo->p_text, 1, strlen(g_p_dealInfo->p_text), p_file);
    assert(len == strlen(g_p_dealInfo->p_text));

    fclose(p_file);
}


int  bx_dealInfo_init(const char *p_path)
{

    assert(NULL != p_path);
    assert(NULL == g_p_dealInfo);

    g_p_dealInfo = malloc(sizeof(bx_dealInfo_t));
    memset(g_p_dealInfo, 0, sizeof(bx_dealInfo_t));

    g_p_dealInfo->buf_len   =   MAX_BUF_SIZE ;
    g_p_dealInfo->max_num =  MAX_DEAL_NUM ;

    FILE *p_file = fopen(p_path, "r");
    if (NULL == p_file)
    {
        g_p_dealInfo->p_text = NULL;
        //若没有文件,则创建JSON句柄
        g_p_dealInfo->p_deal = cJSON_CreateArray();
    }
    else
    {
        g_p_dealInfo->p_text = (char*)malloc(g_p_dealInfo->buf_len + 2048);
        memset(g_p_dealInfo->p_text, 0, g_p_dealInfo->buf_len + 2048);

        //读取文件内容初始化JSON句柄
        int len = fread(g_p_dealInfo->p_text, 1, g_p_dealInfo->buf_len, p_file);
        fclose(p_file);
        assert(0 < len);
        //解析一个对象,并将其返回值给p_deal
        g_p_dealInfo->p_deal = cJSON_Parse(g_p_dealInfo->p_text);
        assert(cJSON_Array == g_p_dealInfo->p_deal->type);
    }

    //g_p_dealInfo->p_mutex = sys_mutex_create();

    //记录文件路径

    strcpy(g_p_dealInfo->path, p_path);

   return 0;
   }

 int bx_deal_quit()
   {
    assert(NULL != g_p_dealInfo);
    assert(NULL != g_p_dealInfo->p_deal);

    g_p_dealInfo->p_deal = NULL;   //
    if (NULL != g_p_dealInfo->p_text)
    {
        //刷新到文件
        event_write();
        free(g_p_dealInfo->p_text);
    }
    cJSON_Delete(g_p_dealInfo->p_deal);

    free(g_p_dealInfo);
    g_p_dealInfo = NULL;

    return 0;
 }

  /// @brief   按下标读取一条信息
  /// @param [in]       seq: 序号
  /// @param [out]      p_dealInfo: 保存交易记录的结构体
  /// @return  0:成功 非0:失败
  // int bx_read_dealInfo(unsigned  int seq,  deal_info_t  *p_dealInfo)

 int bx_read_dealInfo(unsigned  short seq,deal_info_t  *p_dealInfo)
  {
    printf("+++++bx_read_dealInfo++++\n");
    assert(NULL != g_p_dealInfo);
    char *out = NULL;
    cJSON *pArrayItem = NULL;
    //获取数组的节点数量size
    int count = cJSON_GetArraySize(g_p_dealInfo->p_deal);

    pArrayItem = cJSON_GetArrayItem(g_p_dealInfo->p_deal, count-seq);

    printf("***********seq = %d*********\n",seq);
        //将pArrayItem的值以字串的形式打印到char型buffer上,cJSON_Print()会自动分配内存空间,用完需要释放内存。   
    out = cJSON_Print( pArrayItem );        

    printf("%s\n",out);

    //指定格式: 2016/08/30 18:19:30
    //start_time
    printf("++++++++++++++++++++\n");

    cJSON* start_time_temp = cJSON_GetObjectItem(pArrayItem, START_TIME);   
    sscanf(start_time_temp->valuestring, "%d/%d/%d %d:%d:%d\n",     \
        &(p_dealInfo->start_time.year),&(p_dealInfo->start_time.mon),&(p_dealInfo->start_time.mday),   \
        &(p_dealInfo->start_time.hour),&(p_dealInfo->start_time.min),&(p_dealInfo->start_time.sec));

    printf("++++p_dealInfo->start_time.year = %d++++\n",p_dealInfo->start_time.year);
    printf("++++p_dealInfo->start_time.mon = %d++++\n",p_dealInfo->start_time.mon);
    printf("++++p_dealInfo->start_time.mday = %d++++\n",p_dealInfo->start_time.mday);
    printf("++++p_dealInfo->start_time.hour = %d++++\n",p_dealInfo->start_time.hour);
    printf("++++p_dealInfo->start_time.min = %d++++\n",p_dealInfo->start_time.min);
    printf("++++p_dealInfo->start_time.sec = %d++++\n",p_dealInfo->start_time.sec); 
    printf("+++++++++++++++%s(%d)\n",__FILE__,__LINE__);

    //指定格式: 2016/08/30 18:19:30
    //stop_time
    printf("++++++++++++++++++++\n");

    cJSON* stop_time_temp = cJSON_GetObjectItem(pArrayItem, STOP_TIME); 
    sscanf(stop_time_temp->valuestring, "%d/%d/%d %d:%d:%d\n",     \
        &(p_dealInfo->stop_time.year),&(p_dealInfo->stop_time.mon),&(p_dealInfo->stop_time.mday),   \
        &(p_dealInfo->stop_time.hour),&(p_dealInfo->stop_time.min),&(p_dealInfo->stop_time.sec));

    printf("++++p_dealInfo->stop_time.year = %d++++\n",p_dealInfo->stop_time.year);
    printf("++++p_dealInfo->stop_time.mon = %d++++\n",p_dealInfo->stop_time.mon);
    printf("++++p_dealInfo->stop_time.mday = %d++++\n",p_dealInfo->stop_time.mday);
    printf("++++p_dealInfo->stop_time.hour = %d++++\n",p_dealInfo->stop_time.hour);
    printf("++++p_dealInfo->stop_time.min = %d++++\n",p_dealInfo->stop_time.min);
    printf("++++p_dealInfo->stop_time.sec = %d++++\n",p_dealInfo->stop_time.sec);   
    printf("+++++++++++++++%s(%d)\n",__FILE__,__LINE__);

    printf("++++++++++++++++++++\n");
    cJSON* charge_time_temp = cJSON_GetObjectItem(pArrayItem, CHARGE_TIME);
    if(charge_time_temp->valueint == 0)
    {
        printf("++++++++++no_charge++++++++++\n");
        return 0;
    }else{
    p_dealInfo->charge_time = charge_time_temp->valueint;
    printf("++++p_dealInfo->charge_time = %d++++\n",p_dealInfo->charge_time);
    }
    printf("++++++++++++++++++++\n");
    cJSON* total_kwh_temp = cJSON_GetObjectItem(pArrayItem, TOTAL_KWH);
    p_dealInfo->total_kwh = total_kwh_temp->valueint;
    printf("++++p_dealInfo->total_kwh = %d++++\n",p_dealInfo->total_kwh);

        // 释放内存  
        cJSON_Delete(pArrayItem); 

    pArrayItem = NULL;      
    free(out);
    out = NULL;

    return 0;
   }

   /// @brief   获取最新的交易记录下标
   /// @return   最新的交易记录下?
   unsigned short  bx_get_max_index()
   {
    #if 0
    printf("+++++bx_get_max_no++++\n");
    //获取数组的节点数量size
    unsigned short count = cJSON_GetArraySize(g_p_dealInfo->p_deal);
    printf("++++++++++count = %d+++++++++\n",count);
    #endif

    return  0;
   }


   int  bx_write_dealInfo(deal_info_t *p_dealInfo)
   {

    assert(NULL != g_p_dealInfo);
    //assert(NULL !=p_dealInfo);

    printf("+++++bx_write_dealInfo++++\n");

    cJSON* p_data = cJSON_CreateObject();

    //向数组array中插入新的项目
    cJSON_InsertItemInArray(g_p_dealInfo->p_deal, 0, p_data);

    //获取数组的节点数量size
    int count = cJSON_GetArraySize(g_p_dealInfo->p_deal);
    //删除最早的记录
    if (g_p_dealInfo->max_num < count)
        cJSON_DeleteItemFromArray(g_p_dealInfo->p_deal, count - 1);

    //输出该结构体的信息到p_data内 
    char str_time[32] = { 0 };
    sprintf(str_time, "%4d/%02d/%02d %02d:%02d:%02d", p_dealInfo->start_time.year,p_dealInfo->start_time.mon, p_dealInfo->start_time.mday, p_dealInfo->start_time.hour,p_dealInfo->start_time.min,p_dealInfo->start_time.sec);
    cJSON_AddStringToObject(p_data, START_TIME, str_time);

    memset(str_time,0,32);


    sprintf(str_time, "%4d/%02d/%02d %02d:%02d:%02d", p_dealInfo->stop_time.year, p_dealInfo->stop_time.mon, p_dealInfo->stop_time.mday, p_dealInfo->stop_time.hour,p_dealInfo->stop_time.min, p_dealInfo->stop_time.sec);
    cJSON_AddStringToObject(p_data, STOP_TIME, str_time);

    cJSON_AddNumberToObject(p_data, CHARGE_TIME, p_dealInfo->charge_time);

    cJSON_AddNumberToObject(p_data, TOTAL_KWH, p_dealInfo->total_kwh);


    #if 0
    if (NULL != p_dealInfo->p_text)
    {
        free(p_dealInfo->p_text);
        p_dealInfo->p_text = NULL;
    }
    #endif

    if (NULL != g_p_dealInfo->p_text)
    {
        free(g_p_dealInfo->p_text);
        g_p_dealInfo->p_text = NULL;
    }

    //刷新到文件2016.8.25
    //p_dealInfo->p_text = cJSON_PrintUnformatted(p_dealInfo->p_event);
    g_p_dealInfo->p_text = cJSON_Print(g_p_dealInfo->p_deal);

    event_write();

   }

test.c文件:

#include 
#include "cJSON.h"
#include "baoxin_def.h"
#include "bx_deal.h"

//struct deal_info_t *p_dealInfo = NULL; 

struct deal_info_t p_dealInfo;

struct deal_info_t p_dealInfo1 =  
{       
    {2016,8,21,7,15,10,30,0},   //2016/8/25 14:58:30"
    {2016,8,21,7,16,10,30,0},   //"2016/8/25 15:58:30"
    1,
    7
};
struct deal_info_t p_dealInfo2 =  
{       
    {2016,8,22,7,15,10,30,0},   //2016/8/25 14:58:30"
    {2016,8,22,7,16,10,30,0},   //"2016/8/25 15:58:30"
    1,
    7
};
struct deal_info_t p_dealInfo3 =  
{       
    {2016,8,23,7,15,10,30,0},   //2016/8/25 14:58:30"
    {2016,8,23,7,16,10,30,0},   //"2016/8/25 15:58:30"
    1,
    7
};
struct deal_info_t p_dealInfo4 =  
{       
    {2016,8,24,7,15,10,30,0},   //2016/8/25 14:58:30"
    {2016,8,24,7,16,10,30,0},   //"2016/8/25 15:58:30"
    1,
    7
};
struct deal_info_t p_dealInfo5 =  
{       
    {2016,8,25,7,15,10,30,0},   //2016/8/25 14:58:30"
    {2016,8,25,7,16,10,30,0},   //"2016/8/25 15:58:30"
    1,
    7
};
struct deal_info_t p_dealInfo6 =  
{       
    {2016,8,26,7,15,10,30,0},   //2016/8/25 14:58:30"
    {2016,8,26,7,16,10,30,0},   //"2016/8/25 15:58:30"
    1,
    7
};

const char *p_path = "chargeinfo.txt";

//const char *p_path = "/mnt/hgfs/share_for_linux/cJSON_lib_use/chargeinfo.txt";



int main()
{
    bx_dealInfo_init(p_path);
#if 0
    bx_write_dealInfo(&p_dealInfo1);
    bx_write_dealInfo(&p_dealInfo2);
    bx_write_dealInfo(&p_dealInfo3);
    bx_write_dealInfo(&p_dealInfo4);
    bx_write_dealInfo(&p_dealInfo5);    
    bx_write_dealInfo(&p_dealInfo6);
#endif

    bx_get_max_index();
    //bx_read_dealInfo(1,&p_dealInfo);
    bx_read_dealInfo(2,&p_dealInfo);
    //bx_read_dealInfo(3,&p_dealInfo);
    //bx_read_dealInfo(4,&p_dealInfo);
    //bx_read_dealInfo(5,&p_dealInfo);
    //bx_read_dealInfo(6,&p_dealInfo);

    bx_deal_quit();

    //system_pause();

    return 0;

pub_type.h文件:

#ifndef __PUB_TYPE_H__
#define __PUB_TYPE_H__

#include

#ifdef __cplusplus      
#define SK_API extern "C"   
#else       
#define SK_API extern   
#endif

#pragma pack(push) //
#pragma pack(4)

/// @name  _SK_TIME_
/// @brief 时间描述
#if 0
typedef struct SK_TIME
{
   unsigned short      year;       ///< 某年

   unsigned char       mon;        ///< 某月
   unsigned char       mday;       ///< 某日
   unsigned char       wday;       ///< 星期几

    unsigned char       hour;       ///< 时
    unsigned char       min;        ///< 分
    unsigned char       sec;        ///< 秒

    int         msec;              ///< 豪秒
}SK_TIME;
#endif
typedef struct SK_TIME
{
   unsigned short     year;       ///< 某年

   unsigned char       mon;        ///< 某月
   unsigned char       mday;       ///< 某日
   unsigned char       wday;       ///< 星期几

   unsigned char       hour;       ///< 时
   unsigned char       min;        ///< 分
   unsigned char       sec;        ///< 秒

     int       msec;               ///< 豪秒
}SK_TIME;


#pragma pack(pop)//

#endif // __PUB_TYPE_H__
//end

baoxin_def.h:

///////////////////////////////////////////////////////////////////////////
//
/// @file        baoxin.h
/// @brief   与宝信车联网的通信模块
/// @author  
/// @version 0.1
/// @history 修改历史
/// @warning 没有警告
///////////////////////////////////////////////////////////////////////////

#ifndef   __BAO_XIN_DEF_H__
#define   __BAO_XIN_DEF_H__


#include 
#include"pub_type.h"


#define  BX_LOGIN_CODE_LEN  32          //登录码的最大长度
#define  BX_MSG_HEADER_LEN  12          //消息头的最大长度
#define  BX_CELL_PHONE_LEN  12          //终端手机号码的最大长度
#define  BX_MSG_CRC_LEN  1          //校验码长度
#pragma pack(push) //
#pragma pack(1)



typedef struct bx_ser_info_t
{
    unsigned char server[4];   //4个字节,从高位到低位,依次对应IP地址的4个段
    unsigned  short port;       //端口号
}bx_ser_info_t;

typedef  struct  cp_state_t
{
    unsigned char  elec_lock_state ;      
    //电磁锁的状态 0:关闭状态 1:打开状态 2:无电磁锁
    //充电枪的状态 0:充电枪处于与桩连接状态;(暂时无)1:充电枪处于与车连接状态;2:充电枪处于悬空状态;3:充电枪与车连接并且车已经准备好 
    unsigned char  cp_error;              
    //充电桩故障 0:无故障 1:有故障
    //总电量3字节,高8位、中间8位、低8位。总电量,单位为W.H
    unsigned char  current;          
    //充电电流值单位为安培(A)
}cp_state_t;


typedef  struct  login_info_t
{
    unsigned char  login_code[32] ;      //登录码
}login_info_t;


typedef  struct  result_reply_t
{
    unsigned char  answer ;      //充电状态设置结果:0设置成功,1设置失败
}result_reply_t;

typedef  struct  deal_info_t
{
    //unsigned short  seq ;             //查询的交易记录号
    SK_TIME  start_time;            //充电的开始时间
    SK_TIME  stop_time;         //充电的结束时间
    unsigned  int  charge_time; //充电时长
    unsigned  int  total_kwh;        //充电总电度
}deal_info_t;


#pragma pack(pop)//

bx_deal.h文件:

#ifndef __BX_DEAL_H__
#define  __BX_DEAL_H__

#include "pub_type.h"



/// @brief   模块初始化
/// @param [in]       p_fileName: 文件路径
/// @return  0:成功 非0:失败
SK_API  int  bx_deal_init(const char *p_fileName);



/// @brief   模块反初始化
SK_API  int  bx_deal_quit();


/// @brief   按下标读取一条信息
/// @param [in]       seq: 序号
/// @param [out]      p_dealInfo: 保存交易记录的结构体
/// @return  0:成功 非0:失败
/// 将结果存到一个结构体中,即*p_dealInfo;
SK_API int bx_read_dealInfo(unsigned short seq,deal_info_t  *p_dealInfo);

/// @brief   按下标读取一条信息
/// @param [in]       seq: 序号
/// @param [in]       p_dealInfo: 交易记录的结构体
/// @return  0:成功 非0:失败

SK_API int  bx_write_dealInfo(deal_info_t  *p_dealInfo);

/// @brief   获取最新的交易记录下标
/// @return   最新的交易记录下标
SK_API  unsigned short  bx_get_max_index();

#endif

chargeinfo.txt文件:
cJSON的使用介绍及实例分析_第3张图片

小结论:在这个小工程中,运用了cJSON的接口函数,方便让我从人为定义的结构体,这里是包含了充电的信息,将这些信息(结构体)通过cJSON接口函数,以cJSON结构存入指定文件中chargeinfo.txt,并从这个文件以cJSON函数方便的读取出里面的相应序号的充电信息,并以指定的充电信息的结构体形式输出;非常方便;

你可能感兴趣的:(充电桩程序设计)