首页 > 其他分享 >cJson学习(二)

cJson学习(二)

时间:2023-05-11 16:11:21浏览次数:40  
标签:char cJson object 学习 cJSON int key root

已剪辑自: https://blog.csdn.net/ZRXSLYG/article/details/122541036?spm=1001.2101.3001.6650.17&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-17-122541036-blog-123806149.235^v35^pc_relevant_default_base&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-17-122541036-blog-123806149.235^v35^pc_relevant_default_base&utm_relevant_index=18

安装

https://github.com/DaveGamble/cJSON

组包

#include <stdio.h>
#include "cJSON.h"

int main(){
    // 创建dict结点
    cJSON *root = cJSON_CreateObject();

    // 添加string子节点
    cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));

    // 添加number子节点
    cJSON_AddItemToObject(root, "age", cJSON_CreateNumber(20));

    // 添加bool子节点
    cJSON_AddItemToObject(root, "best", cJSON_CreateBool(cJSON_True));

    // 添加bool子节点
    cJSON_AddItemToObject(root, "worse", cJSON_CreateFalse());

    // 添加NULL子节点
    cJSON_AddItemToObject(root, "address", cJSON_CreateNull());

    // 添加array
    cJSON *string_array = cJSON_CreateArray();
    cJSON_AddItemToObject(string_array,"hello",cJSON_CreateString("hello"));
    cJSON_AddItemToObject(string_array,"world",cJSON_CreateString("world"));
    cJSON_AddItemToObject(root,"string",string_array);

    // 添加array
    int nums[] = {1,2,3,4,5,6};
    cJSON *nums_array = cJSON_CreateIntArray(nums,sizeof(nums)/sizeof(int));
    cJSON_AddItemToObject(root,"nums",nums_array);

    // 格式化输出, 调用malloc
    printf("%s\n",cJSON_Print(root));

    // 非格式化输出, 调用malloc
    printf("%s\n",cJSON_PrintUnformatted(root));

    // 不调用malloc
    char buffer[4096] = {0};
    cJSON_PrintPreallocated(root,buffer,sizeof(buffer),0);//0 非格式化, 1格式化
    printf("%s\n",buffer);

    // 删除节点, 如果直接调用cJSON_Delete删除某个节点, print的时候会出错的
    cJSON_DeleteItemFromObjectCaseSensitive(root,"age");// 大小写敏感
    // cJSON_DeleteItemFromObject// 大小写不敏感

    // 更新节点
    cJSON_ReplaceItemInObjectCaseSensitive(root,"name",cJSON_CreateString("小明"));// 大小写敏感
    // cJSON_ReplaceItemInObject// 大小写不敏感

    // 格式化输出, 调用malloc
    printf("%s\n",cJSON_Print(root));

    // 删除根节点
    cJSON_Delete(root);
}

解包

#include <stdio.h>
#include "cJSON.h"

int main(){
    char s[] = "{\"name\":\"Jack (\\\"Bee\\\") Nimble\",\"age\":20,\"best\":true,\"worse\":false,\"address\":null,\"string\":[\"hello\",\"world\"],\"nums\":[1,2,3,4,5,6]}";

    cJSON *root, *object, *sub_object;
    
    // 解析
    root = cJSON_Parse(s);

    // 字符串
    object = cJSON_GetObjectItemCaseSensitive(root,"name");
    printf("%d %s\n",cJSON_IsString(object), cJSON_GetStringValue(object));
    object = cJSON_GetObjectItem(root,"NAME");
    printf("%d %s\n",cJSON_IsString(object), cJSON_GetStringValue(object));
    

    // 数字
    object = cJSON_GetObjectItemCaseSensitive(root,"age");
    printf("%d %lf\n",cJSON_IsNumber(object), cJSON_GetNumberValue(object));

    // 数组
    object = cJSON_GetObjectItemCaseSensitive(root,"string");
    printf("%d %d\n",cJSON_IsArray(object), cJSON_GetArraySize(object));
    int i,n = cJSON_GetArraySize(object);
    for(i=0;i<n;i++){
        sub_object = cJSON_GetArrayItem(object,i);
        printf("%d %s\n",cJSON_IsString(sub_object), cJSON_GetStringValue(sub_object));
    }

    // 删除根节点
    cJSON_Delete(root);
}

解包与可变参数

#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "cJSON.h"

#define get_cjson_string(args...) _get_cjson_string(args,"")
int _get_cjson_string(cJSON * root, char * value, int value_size, ...)
{
    va_list ap;
    char *key;
    cJSON *object;

    va_start(ap, value_size);
    for(key=va_arg(ap, char*),object=root;key[0]!='\0';key=va_arg(ap, char*)){
        object = cJSON_GetObjectItemCaseSensitive(object,key);
        if(object == NULL){
            printf("no find %s\n",key);
            break;
        }
    }
    
    va_end(ap);

    if(object==NULL || !cJSON_IsString(object)){
        return -1;
    }

    int len = strlen(cJSON_GetStringValue(object));
    if(len > value_size){
        return -1;
    }

    strcpy(value,cJSON_GetStringValue(object));
    return len;
}

#define get_cjson_number(args...) _get_cjson_number(args,"")
int _get_cjson_number(cJSON * root, double * value, ...){
    va_list ap;
    char *key;
    cJSON *object;

    va_start(ap, value);
    for(key=va_arg(ap, char*),object=root;key[0]!='\0';key=va_arg(ap, char*)){
        object = cJSON_GetObjectItemCaseSensitive(object,key);
        if(object == NULL){
            printf("no find %s\n",key);
            break;
        }
    }
    
    va_end(ap);

    if(object==NULL || !cJSON_IsNumber(object)){
        return -1;
    }

    *value = cJSON_GetNumberValue(object);
    return 0;
}

#define get_cjson_object(args...) _get_cjson_object(args,"")
cJSON * _get_cjson_object(cJSON * root, ...){
    va_list ap;
    char *key;
    cJSON *object;

    va_start(ap, root);
    for(key=va_arg(ap, char*),object=root;key[0]!='\0';key=va_arg(ap, char*)){
        object = cJSON_GetObjectItemCaseSensitive(object,key);
        if(object == NULL){
            printf("no find %s\n",key);
            break;
        }
    }
    
    va_end(ap);

    return object;
}

int main(){
    char s[] = "{\"name\":\"Jack (\\\"Bee\\\") Nimble\",\"age\":20,\"best\":true,\"worse\":false,\"address\":null,\"string\":[\"hello\",\"world\"],\"nums\":[1,2,3,4,5,6]}";

    cJSON *root, *object, *sub_object;
    
    // 解析
    root = cJSON_Parse(s);

    // 字符串
    char tmp[1024] = {0};
    get_cjson_string(root,tmp,sizeof(tmp)-1,"name");
    printf("%s\n",tmp);
    

    // 数字
    double f = 0.0;
    get_cjson_number(root,&f,"age");
    printf("%lf\n",f);

    // 删除根节点
    cJSON_Delete(root);
}

优化

重定义malloc和free, 可以优化组包解包速度
因为绝大部分场景,基本都是调用malloc生成新节点,然后在最后delete根节点的时候一起free释放所有节点。所以可以预先在堆中定义一个大buffer, malloc则从buffer中申请

#include <stdio.h>
#include "cJSON.h"

int main(int argc,char** argv){
   unsigned char buff[8192],*p = buff;
   void *my_malloc(size_t sz){
       if(sizeof(buff) - (p-buff) < sz){
           return NULL;
       }
       unsigned char *p_tmp = p;
       p += sz;
       return p_tmp;
   }
   void my_free(void* ptr){
       return;
   }

   cJSON_Hooks hooks = {my_malloc,my_free};
   cJSON_InitHooks(&hooks);// 替换原有的malloc和free

   cJSON *root,*fmt;
   root = cJSON_CreateObject();
   cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
   cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject());
   cJSON_AddStringToObject(fmt, "type", "rect");
   cJSON_AddNumberToObject(fmt, "width", 1920);
   cJSON_AddNumberToObject(fmt, "height", 1080);
   cJSON_AddFalseToObject (fmt, "interlace");
   cJSON_AddNumberToObject(fmt, "frame rate", 24);
   printf("%s\n",cJSON_PrintUnformatted(root));
   cJSON_Delete(root);

   cJSON_InitHooks(NULL);// 还原为原有的malloc和free
}

测试程序
测试环境:树莓派4B
test_stack.c
#include <stdio.h>
#include "cJSON.h"

int main(int argc,char** argv){
   int n = 10000,i;
   if(argc > 1){
       n = atoi(argv[1]);
   }

   for(i=0;i<n;i++){
       unsigned char buff[8192],*p = buff;
       void *my_malloc(size_t sz){
           if(sizeof(buff) - (p-buff) < sz){
               return NULL;
           }
           unsigned char *p_tmp = p;
           p += sz;
           return p_tmp;
       }
       void my_free(void* ptr){
           return;
       }

       cJSON_Hooks hooks = {my_malloc,my_free};
       cJSON_InitHooks(&hooks);

       cJSON *root,*fmt;
       root = cJSON_CreateObject();
       cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
       cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject());
       cJSON_AddStringToObject(fmt, "type", "rect");
       cJSON_AddNumberToObject(fmt, "width", 1920);
       cJSON_AddNumberToObject(fmt, "height", 1080);
       cJSON_AddFalseToObject (fmt, "interlace");
       cJSON_AddNumberToObject(fmt, "frame rate", 24);
       // printf("%s\n",cJSON_PrintUnformatted(root));
       cJSON_Delete(root);
       cJSON_InitHooks(NULL);
   }
}

test_heap.c
#include <stdio.h>
#include "cJSON.h"

int main(int argc,char** argv){
   int n = 10000,i;
   if(argc > 1){
       n = atoi(argv[1]);
   }

   for(i=0;i<n;i++){
       cJSON *root,*fmt;
       root = cJSON_CreateObject();
       cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
       cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject());
       cJSON_AddStringToObject(fmt, "type", "rect");
       cJSON_AddNumberToObject(fmt, "width", 1920);
       cJSON_AddNumberToObject(fmt, "height", 1080);
       cJSON_AddFalseToObject (fmt, "interlace");
       cJSON_AddNumberToObject(fmt, "frame rate", 24);
       // printf("%s\n",cJSON_PrintUnformatted(root));
       cJSON_Delete(root);
   }
   
   
}

Makefile

SRC = $(wildcard *.c)
OBJ = $(patsubst %.c, %.o, $(SRC))

all : test_stack test_heap

test_stack:test_stack.o cJSON.o
    gcc -o $@ $^

test_heap:test_heap.o cJSON.o
    gcc -o $@ $^

$(OBJ):%.o:%.c
    gcc -c -o $@ $< -O3

clean:
    -rm $(OBJ) $(all)

.PHONY:all clean

1000000次循环测试结果

> time ./test_stack 1000000

real    0m0.868s
user    0m0.867s
sys     0m0.000s

> time ./test_heap 1000000

real    0m3.093s
user    0m3.093s
sys     0m0.000s

参考:

https://blog.csdn.net/Mark_md/article/details/108548524
https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap
https://stackoverflow.com/questions/24057331/is-accessing-data-in-the-heap-faster-than-from-the-stack
https://stackoverflow.com/questions/161053/which-is-faster-stack-allocation-or-heap-allocation
https://stackoverflow.com/questions/2264969/why-is-memory-allocation-on-heap-much-slower-than-on-stack

标签:char,cJson,object,学习,cJSON,int,key,root
From: https://www.cnblogs.com/sggggr/p/17391373.html

相关文章

  • 学习日记——表单的语法、运用和验证
    1.语法①邮箱<formaction="demo001.html"><tableborder="1px"><tr><td>请输入邮箱地址<inputtype="email"name=""id=""value=""/......
  • Day01 Markdown学习
    Markdown学习标题三级标题四级标题字体两边加星号变粗体两边一个星号变斜体一个星两个星斜体加粗两边两个波浪号删除线引用一个>符号出引用效果分割线三个减号三个星号图片![截图](C:\Users\GE62\Pictures\CameraRoll\002.jpg)超链接点击跳转到狂神说JAVA......
  • PE学习——PE文件整体结构解析,写得很精致,可以对照案例实践
    PE文件结构: PE加载到内存后的映射: 我们本章节主要看上述细节。本文最核心的图就是PE在做image内存展开的样子: PE文件整体结构解析之前我们已经按照PE文件的整体结构对实际的PE文件进行了大致上的了解了,现在我们需要来看看每个结构的意义和作用。DOS头在之前,我们......
  • PSO-CNN-LSTM,即粒子群优化CNN_LSTM网络做预测的算法,优化隐含层单元个数和初始学习率,预
    PSO-CNN-LSTM,即粒子群优化CNN_LSTM网络做预测的算法,优化隐含层单元个数和初始学习率,预测精度要比CNN-LSTM高。ID:74150668460757943......
  • python 学习-打开潘多拉的魔盒-元类(metaclass)学习
    前言在Python里面大家都比较熟悉了,通过class关键字创建一个类,这是通过硬编码来实现的。那么如何动态创建一个类呢,如果给一批数据,让它动态生成一个类?学习警告:不要轻易打开潘多拉的魔盒,潘多拉出于好奇打开一个魔盒,释放出人世间的所有邪恶:贪婪、虚无、诽谤、嫉妒、痛苦等等......
  • kubernetes学习笔记27:etcd性能
    理解etcd性能:etcd集群架构图,包含raft层,storage层(storage层包含treeindex层和boltdb底层持久化存储key-value层),它们每一层都可能造成性能损失,raft层需要网络同步数据,网络io节点之间的rtt和带宽都会影响etcd性能,另外wal也会受到磁盘io的写入速度影响。storage层,磁盘iofdatasync延迟......
  • 【C++学习笔记】C++ 正则表达式不完全支持零断宽言
    最近需要解析配置文件,遇到从@STARTDATA@END中提取DATA的正则,按照C#的操作,直接(?<=@START)[\W\w]?(?=@END),就能提取的,可是在C++中,regexe("(?<=@START)[\W\w]?(?=@END)")报错了,找了很多说法,最终结论:支持先行断言,不支持后行断言即:(?<=@START)和(?<!@START)。好在C++支持子匹......
  • python基础学习-hashlib - 哈希函数模块
    hashlib-哈希函数模块参考地址:Python-Core-50-Courses/第20课:Python标准库初探.mdatmaster·jackfrued/Python-Core-50-Courses(github.com)待补充......哈希函数又称哈希算法或散列函数,是一种为已有的数据创建“数字指纹”(哈希摘要)的方法。哈希函数把数据压缩成摘要,对......
  • python基础学习-random
    参考地址:Python-Core-50-Courses/第20课:Python标准库初探.mdatmaster·jackfrued/Python-Core-50-Courses(github.com)待补充......random-随机数和随机抽样模块生成随机数、实现随机乱序和随机抽样,下面是常用函数的列表。getrandbits(k):返回具有k个随机比特位的整数......
  • python基础学习-os.path - 路径操作相关模块
    参考地址:Python-Core-50-Courses/第20课:Python标准库初探.mdatmaster·jackfrued/Python-Core-50-Courses(github.com)待补充......os.path模块封装了操作路径的工具函数,如果程序中需要对文件路径做拼接、拆分、获取以及获取文件的存在性和其他属性,这个模块将会非常有帮助......