cJson解析与base64解码的原型验证

cJson解析与base64解码的原型验证

base64.h


#ifndef _BASE64_H
#define _BASE64_H

#include <stdint.h>    
int bin_to_b64_nopad(const uint8_t * in, int size, char * out, int max_len);
int b64_to_bin_nopad(const char * in, int size, uint8_t * out, int max_len);


int bin_to_b64(const uint8_t * in, int size, char * out, int max_len);
int b64_to_bin(const char * in, int size, uint8_t * out, int max_len);

#endif
 

 cJSON.h

 

#ifndef cJSON__h
#define cJSON__h

#ifdef __cplusplus
extern "C"
{
#endif

/* cJSON Types: */
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6
    
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512

/* The cJSON structure: */
typedef struct cJSON {
    struct cJSON *next,*prev;    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
    struct cJSON *child;        /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */

    int type;                    /* The type of the item, as above. */

    char *valuestring;            /* The item's string, if type==cJSON_String */
    int valueint;                /* The item's number, if type==cJSON_Number */
    double valuedouble;            /* The item's number, if type==cJSON_Number */

    char *string;                /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;

typedef struct cJSON_Hooks {
      void *(*malloc_fn)(size_t sz);
      void (*free_fn)(void *ptr);
} cJSON_Hooks;

/* Supply malloc, realloc and free functions to cJSON */
extern void cJSON_InitHooks(cJSON_Hooks* hooks);


/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
/*提供一个JSON块,然后返回一个可以查询的cJSON对象。完成后调用cJSON_Delete。*/
extern cJSON *cJSON_Parse(const char *value);

/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
/*将cJSON实体呈现为用于传输/存储的文本。完成后释放char*。*/
extern char  *cJSON_Print(cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
extern char  *cJSON_PrintUnformatted(cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt);
/* Delete a cJSON entity and all subentities. */
/*删除一个cJSON实体和所有子实体。*/
extern void   cJSON_Delete(cJSON *c);

/* Returns the number of items in an array (or object). */
extern int      cJSON_GetArraySize(cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
/* Get item "string" from object. Case insensitive. */
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);

/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
extern const char *cJSON_GetErrorPtr(void);
    
/* These calls create a cJSON item of the appropriate type. */
extern cJSON *cJSON_CreateNull(void);
extern cJSON *cJSON_CreateTrue(void);
extern cJSON *cJSON_CreateFalse(void);
extern cJSON *cJSON_CreateBool(int b);
extern cJSON *cJSON_CreateNumber(double num);
extern cJSON *cJSON_CreateString(const char *string);
extern cJSON *cJSON_CreateArray(void);
extern cJSON *cJSON_CreateObject(void);

/* These utilities create an Array of count items. */
/*这些共用工具创建 一些 对象*/
extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
extern cJSON *cJSON_CreateStringArray(const char **strings,int count);

/* Append item to the specified array/object. */
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
extern void    cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
extern void    cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item);    /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */

/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
/*将对项的引用追加到指定的数组/对象。当您想要将现有的cJSON添加到新的cJSON中,但又不想破坏现有的cJSON时,可以使用此方法。*/
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
extern void    cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);

/* Remove/Detach items from Arrays/Objects. */
/*从数组/对象中删除/分离项*/
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
extern void   cJSON_DeleteItemFromArray(cJSON *array,int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
extern void   cJSON_DeleteItemFromObject(cJSON *object,const char *string);
    
/* Update array items. */
/*更新数组项*/
extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem);    /* Shifts pre-existing items to the right. */
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);

/* Duplicate a cJSON item */
/*复制一个cJSON对象*/
extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
need to be released. With recurse!=0, it will duplicate any children connected to the item.
The item->next and ->prev pointers are always zero on return from Duplicate. */

/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/*ParseWithOpts允许您要求(并检查)JSON是否为null终止,并检索指向解析后的最终字节的指针。*/
extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);

/*minify 使变小  削减*/
extern void cJSON_Minify(char *json);   


/* Macros for creating things quickly. */
/*用于快速创建内容的宏。*/
#define cJSON_AddNullToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
#define cJSON_AddFalseToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
#define cJSON_AddBoolToObject(object,name,b)    cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
#define cJSON_AddNumberToObject(object,name,n)    cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object,name,s)    cJSON_AddItemToObject(object, name, cJSON_CreateString(s))


/* When assigning an integer value, it needs to be propagated to valuedouble too. */
/*在分配整数值时,也需要将其传播到valuedouble*/
#define cJSON_SetIntValue(object,val)            ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
#define cJSON_SetNumberValue(object,val)        ((object)?(object)->valueint=(object)->valuedouble=(val):(val))

#ifdef __cplusplus
}
#endif

#endif
 

//注意:绿色标记的声明是用来进行解析Json格式的,其他的函数是用来封装Json格式的。

 json_up (要解析的Json文件)

{
    "rxpk": [{
        "tmst": 66317107,
        "chan": 2,
        "rfch": 1,
        "freq": 471.500000,
        "stat": 1,
        "modu": "LORA",
        "datr": "SF7BW125",
        "codr": "4/5",
        "lsnr": 9.2,
        "rssi": 3,
        "size": 15,
        "data": "QAEAAAAABQACSnK5CpM9"
    }]
}

40 01 00 00 00 00 05 00 02 4A 72 B9 0A 93 3D 

 mainTest.cpp

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>  /*   strlen  */
#include "cJSON.h"
#include "base64.h"
using namespace std;

/* Parse text to JSON, then render back to text, and print! */
void doit(char *text)
{
    char *out; cJSON *json;  //要进行释放

    json = cJSON_Parse(text);
    if (!json) { printf("Error before: [%s]\n", cJSON_GetErrorPtr()); }
    else
    {
        out = cJSON_Print(json);
        cJSON_Delete(json);
        printf("%s\n", out);
        free(out);
    }
}

int parse_up(char *parse_data) {
    uint8_t outBuf[256];
    memset(outBuf, 0, sizeof outBuf);

    //1.打包Json字符串
    cJSON *cjson = cJSON_Parse(parse_data);
    //1.1.判断是否打包成功
    if (cjson == NULL) {
        printf("cjson parse data error…");
        exit(0);
    }
    
    //3.获取数组对象 cJSON_GetObjectItem
    cJSON *rxpk = cJSON_GetObjectItem(cjson, "rxpk");

    //4.获取数组对象个数便于循环
    int arr_size = cJSON_GetArraySize(rxpk);  //return arr_size 1

    //5.获取test_arr数组对象孩子节点
    cJSON* arr_item = rxpk->child;//子对象

    //6.循环获取数组下每个字段的值并使用cJSON_Print打印
    cJSON *tmst = cJSON_GetObjectItem(arr_item, "tmst");
    printf("tmst=%d\n", tmst->valueint);
    cJSON *datr = cJSON_GetObjectItem(arr_item, "datr");
    printf("datr=%s\n", datr->valuestring);
    cJSON *data = cJSON_GetObjectItem(arr_item, "data");
    printf("data=%s\n", data->valuestring);

    //进行解码操作
    const char *str = (const char*)(data->valuestring);
    int len = strlen(data->valuestring);
    cout << "str=" << str << "   " << "len=" << len << endl;

    int ret=b64_to_bin((const char*)(data->valuestring), strlen(data->valuestring), outBuf, sizeof outBuf);
    if (ret == 0) {
        printf("base64解密失败!\n");
        return 0;
    }
    //printf("De_outBuf=%x\n",outBuf);
    //cout << "De_outBuf[]=" << outBuf << endl;
    unsigned int outBuf_len = strlen((const char *)outBuf);
    cout << "outBuf_len= "<<outBuf_len << endl;
    for (unsigned int m = 0; m < outBuf_len; m++) {
        printf("%#x ", outBuf[m]);
    }
    printf("\n\n");
    for (int m = 0; m < 20; m++) {
        printf("%#x ", outBuf[m]);
    }
    //arr_item = arr_item->next;//下一个子对象
    return 0;
}

/* Read a file, parse, render back, etc. */
void dofile_up(const char *filename)
{
    FILE *f; long len; char *data;

    f = fopen(filename, "rb");
    fseek(f, 0, SEEK_END);
    len = ftell(f);
    fseek(f, 0, SEEK_SET);

    data = (char*)malloc(len + 1);

    fread(data, 1, len, f);
    fclose(f);

    doit(data);
    //解析data数据
    parse_up(data);

    free(data);
}


int main(int argc, const char * argv[]) {
    
    /* Parse standard testfiles: */
    dofile_up("json_up");

    system("pause");
    return 0;
}

运行结果:

 cJson解析与base64解码的原型验证

test6

{
    "test_1": "1",
    "test_2": "2",
    "test_arr": [{

            "test_1": "arr_1",
            "test_2": "arr_2",
            "test_3": "arr_3"
        },
        {
            "test_1": "1",
            "test_2": "2",
            "test_3": "3"
        }
    ],
    "test_3": "3"
}

ceshi_test6.cpp

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>  /*   strlen  */
#include "cJSON.h"
#include "base64.h"
using namespace std;

/* Parse text to JSON, then render back to text, and print! */
void doit(char *text)
{
    char *out; cJSON *json;

    json = cJSON_Parse(text);
    if (!json) { printf("Error before: [%s]\n", cJSON_GetErrorPtr()); }
    else
    {
        out = cJSON_Print(json);
        cJSON_Delete(json);
        printf("%s\n", out);
        free(out);
    }
}

int parse_up(char *parse_data) {
    //第一步打包JSON字符串
    cJSON* cjson = cJSON_Parse(parse_data);

    //判断是否打包成功
    if (cjson == NULL) {
        printf("cjson error…");
    }
    
    //获取数组对象
    cJSON* test_arr = cJSON_GetObjectItem(cjson, "test_arr"); 

    //获取数组对象个数便于循环
    int arr_size = cJSON_GetArraySize(test_arr);//return arr_size 2
    cout << arr_size << endl;
    //获取test_arr数组对象孩子节点
    cJSON* arr_item = test_arr->child;//子对象

     //循环获取数组下每个字段的值并使用cJSON_Print打印
    for (int i = 0; i <= (arr_size - 1)/*0*/; ++i) {
        char *out = cJSON_Print(cJSON_GetObjectItem(arr_item, "test_1"));
        printf("%s\n", out);free(out);

        out = cJSON_Print(cJSON_GetObjectItem(arr_item, "test_2"));
        printf("%s\n", out); free(out);
        
        out = cJSON_Print(cJSON_GetObjectItem(arr_item, "test_3"));
        printf("%s\n", out); free(out);

        arr_item = arr_item->next;//下一个子对象
    }

    //获取“test_1” “test_2” “test_3”
    cJSON *test_3 = cJSON_GetObjectItem(cjson, "test_3");
    printf("test_3 : %s\n",test_3->valuestring);

    cJSON *test_2 = cJSON_GetObjectItem(cjson, "test_2");
    printf("test_2 : %s\n", test_2->valuestring);

    //delete cjson 这里只需要释放cjson即可,因为其它的都指向它
    cJSON_Delete(cjson);
    return 0;
}


/* Read a file, parse, render back, etc. */
void dofile_up(const char *filename)
{
    FILE *f; long len; char *data;

    f = fopen(filename, "rb");
    fseek(f, 0, SEEK_END);
    len = ftell(f);
    fseek(f, 0, SEEK_SET);

    data = (char*)malloc(len + 1);

    fread(data, 1, len, f);
    fclose(f);

    doit(data);
    //解析data数据
    parse_up(data);

    free(data);
}


int main(int argc, const char * argv[]) {

    
    dofile_up("test6");
    

    system("pause");
    return 0;
}

 运行结果:

cJson解析与base64解码的原型验证