热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

cjson:json字符串的理解

一、cjson概念cJSON是一款开源的轻量级数据格式解析封装库,在嵌入式中的应用场景是非常多的,其中就有我们日常使用的天气,还有很多公司

一、cjson概念
cJSON是一款开源的轻量级数据格式解析封装库,在嵌入式中的应用场景是非常多的,其中就有我们日常使用的天气,还有很多公司让cJSON和MQTT协议相结合,终端用它来向服务器上报参数、日志信息或者服务器向终端发送指令。这就需要用到cJSON来将这串字符串解析成我们需要的数据,或者将需要上报的信息封装成cJSON格式,这样相互通信的两端才能得到自己想要的数据。过一个具体的例子来说明一下,首先去官网把这个库下载下来,官网的地址:https://sourceforge.net/projects/cjson/,下载下来后有两个文件是需要提取出来的就是cJSON.c和cJSON.h。然后通过GET请求接收一段天气的内容。具体的GET请求涉及到socket网络编程和HTTP协议。
JSON里面主要是按照键值对(key : value)的方式来存储数据的,所以我们提取数据就按照键的名字直接提取,存入数据,就将想要存入的数据取一个名字(即字符串)然后放到JSON结构体里面就可以了。
这是一个典型的JSON结构体,我们可以看到,键名为“name”的值对应为"John Doe",而键名“address”的值则是一个用大括号括起来的数据,这是区别于c语言的一种数据类型,我们把它叫做对象。
给出一个json例子,让大家有个体会:
{
“name”: “John Doe”,
“age”: 18,
“address”: {“country” : “china”, “zip-code”: “10000”}
}

二、json是干什么的
其实使用CJSON和JSON其实只是为了干一件事:那就是解析收到的数据和发送对方能够解析的数据,那么cjson就是我们用的工具,我们用这个工具来编辑和解析JSON格式的数据。

三、json数据分类
作为熟悉C语言的大家,json其实只有两种区别于c语言的数据类型,我们看看这两种就可以啦。
1、对象:json数据的主要单位,也就是一个用大括号括起来的数据,他包含的所有数据是各种键值对,键值对之间用逗号加以区分。注意我们用cjson操作时,也主要是对对象的操作
2、键值对:json数据的基本单位,键值对的键名必须是一个字符串,而键值则可以是int,double,string,array等各种数据。中间用冒号链接。
例如:
/**对象/
//对象:用大括号括起来的数据:
{“name”:“hello”}

/*键值对/
//数组:用中括号括起来的数据:
{“array”:[1,2,3]}
//字符串键值对
“key”:“value”
//number键值对
“number”:2

四、json数据如何传输
我们现在已经知道json数据是一个结构体,那么如何传输结构体了?要知道,数据在网络或者无线通信中传输的都是二进制数据,我们如果要按照特殊的通讯协议来传输的话,我们就要按照这个协议解析。所以按照这个规则,我们直接双方都采用json格式的数据,然后采用相同的方式解析就可以啦。
这种方式大家都非常熟悉,我们直接将JSON数据转换成为字符串,然后传输,之后将字符串解析成JSON数据就可以啦。

五、cjson结构体
/* The cJSON structure: */
typedef struct cJSON
{
//这些不用管
struct cJSON *next;
struct cJSON *prev;
struct cJSON *child;

//这些都要知道
//该json对象的类型,可以是字符串,int,double…
int type;
/* The item’s string, if typecJSON_String and type == cJSON_Raw */
//如果类型是字符串,那么键值的字符串的值存在这里
char valuestring;
/
writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead /
//如果类型是int,那么值存在这里
int valueint;
/
The item’s number, if type
cJSON_Number /
//如果类型是double,那么值存在这里
double valuedouble;
/
The item’s name string, if this item is the child of, or is in the list of subitems of an object. */
//存放名字的地方
char *string;
} cJSON;

六、cjson解析和构造函数
下面都是将JSON结构体转换为字符串数据的操作函数:
//将CJSON数据转换为字符串(保留原来的格式:例如会保留空格和回车)
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
//将CJSON数据转换为字符串(删除所有格式,只保留文本)
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
//将CJSON数据转换为字符串(并且存储到一个buffer里面)
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
//将CJSON数据转换为字符串(储存到一个动态申请的空间中)
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);

下面都是将JSON字符串转换为JSON结构体的操作:

//将json字符串转换为结构体,并且将其赋给一个指针
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
//将json字符串转换为结构体,并且将其赋给一个指针,这个函数会提供一些操作选项来帮助开发者使用
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);

七、cjson创建键值的两种方法
1、将cjson对象加入:这个方法关键在于,首先需要先创建一个对象然后再将他加入进去。
//常用
//将对象加入数组或者对象
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemToObject(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.


  • WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
  • writing to item->string */
    CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON item);
    /
    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_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
    CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);

2、 直接将键值和名字填入构建为一个键值对:不需要构建新的结构体。
/* Helper functions for creating and adding items to an object at the same time.


  • They return the added item or NULL on failure. /
    //我们想添加什么数据就可以直接添加,不用另外构建CJSON结构体
    CJSON_PUBLIC(cJSON
    ) cJSON_AddNullToObject(cJSON * const object, const char * const name);
    CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
    CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
    CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
    CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
    CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
    CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
    CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
    CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);

八、cjson获取键值对的方法
从json结构体里面提取我们想要的键值:
/* Returns the number of items in an array (or object). */
//获取数组大小
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON array);
/
Retrieve item number “index” from array “array”. Returns NULL if unsuccessful. */
//获取数组里面的某一个值
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON array, int index);
/
Get item “string” from object. Case insensitive. */
//这个函数将某一个键值对,提取出来放到一个结构体中
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);

//以下都不常用
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const 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. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);

/* Check if the item is a string and return its valuestring */
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);

九、cjson操作实例
我们使用CJSON其实只有两种操作:
1、构建JSON结构,然后转换为字符串来发送或者做其他的。
2、解析别人发来的JSON字符串,然后转换为结构体,然后读取里面的数据,找到对应的值

3、创建自己的:创建、添加、变换
/创建******/
//构建最后用于存放JSON数据的字符串
char * json_buffer = { 0 };
//首先构造一个根对象指针:
cJSON* root = NULL;
//创建String对象指针:
cJSON* string = NULL;
//创建int对象指针:
cJSON* int_number = NULL;
//创建数组指针:
cJSON* array = NULL;
int the_array[3] = { 1,2,3 };
//创建一个根对象,给root
root = cJSON_CreateObject();
//创建一个字符串对象,给string
string = cJSON_CreateString(“hello world”);
//创建一个int对象,给int_number
int_number = cJSON_CreateNumber(10);
//创建一个array对象,给array
array = cJSON_CreateIntArray(the_array, 3);
/添加******/
//将字符串string加入根对象,成为一个键值对:

//方法一:添加对象
cJSON_AddItemToObject(root,"string",string);
//方法二:直接添加
cJSON_AddStringToObject(root,"string_1","bye world");//添加剩下的
cJSON_AddItemToObject(root,"int_number",int_number);
cJSON_AddItemToObject(root,"array ",array);/***************************变换*********************************/
json_buffer = cJSON_PrintUnformatted(root);
printf("json_buffer is %s\n", json_buffer);

创建后返回的结果如下:
json_buffer is {“string”:“hello world”,“string_1”:“bye world”,“int_number”:10,"array ":[1,2,3]}

4、解析收到的:解析、获取、打印
//JSON字符串
const char* json_str = “{“name”:“json_test”,“num”:“520”,“arry”:[1,2,3]}”;
cJSON* temp = 0;
/解析*******/
cJSON* json = NULL;
cJSON* name = NULL;
cJSON* num = NULL;
cJSON* arry = NULL;

/****************************获取***********************************/
//将字符串解析为一个结构体
json = cJSON_Parse(json_str);
name = cJSON_GetObjectItem(json,"name");
num = cJSON_GetObjectItem(json, "num");
arry = cJSON_GetObjectItem(json, "arry");printf("name is %s\n", name->valuestring);
printf("num is %d\n", num->valueint);
temp = cJSON_GetArrayItem(arry, 1);
printf("arry[0] is %d\n", temp->valueint);

解析后返回的结果如下:
name is json_test
num is 0
arry[0] is 2

十、实例
/** CJSON使用例子


  • CJSON template
  • Author:jiang shan (github: jianggogogo)
  • date: 2019.12.25
  • Note: This file is open to learning.
  • licence:
    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the “Software”), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include “stdio.h”
#include “cJSON.h”
#include “stdlib.h”

//创建一个JSON数据并且转换为字符串
void Create_print()
{
/创建******/
//构建最后用于存放JSON数据的字符串
char* json_buffer = { 0 };
//首先构造一个根对象指针:
cJSON* root = NULL;
//创建String对象指针:
cJSON* string = NULL;
//创建int对象指针:
cJSON* int_number = NULL;
//创建数组指针:
cJSON* array = NULL;
int the_array[3] = { 1,2,3 };
//创建一个根对象,给root
root = cJSON_CreateObject();
//创建一个字符串对象,给string
string = cJSON_CreateString(“hello world”);
//创建一个int对象,给int_number
int_number = cJSON_CreateNumber(10);
//创建一个array对象,给array
array = cJSON_CreateIntArray(the_array, 3);
/添加******/
//将字符串string加入根对象,成为一个键值对:

//方法一:添加对象
cJSON_AddItemToObject(root, "string", string);
//方法二:直接添加
cJSON_AddStringToObject(root, "string_1", "bye world");//添加剩下的
cJSON_AddItemToObject(root, "int_number", int_number);
cJSON_AddItemToObject(root, "array ", array);/***************************变换*********************************/
json_buffer = cJSON_PrintUnformatted(root);
printf("json_buffer is %s\n", json_buffer);cJSON_Delete(root);

}

//解析字符串并且读取里面的数据
void prase_print()
{
//JSON字符串
const char* json_str = “{“name”:“json_test”,“num”:“520”,“arry”:[1,2,3]}”;
cJSON* temp = 0;
/解析*******/
cJSON* json = NULL;
cJSON* name = NULL;
cJSON* num = NULL;
cJSON* arry = NULL;

/****************************获取***********************************/
//将字符串解析为一个结构体
json = cJSON_Parse(json_str);
name = cJSON_GetObjectItem(json,"name");
num = cJSON_GetObjectItem(json, "num");
arry = cJSON_GetObjectItem(json, "arry");printf("name is %s\n", name->valuestring);
printf("num is %d\n", num->valueint);
temp = cJSON_GetArrayItem(arry, 1);
printf("arry[0] is %d\n", temp->valueint);cJSON_Delete(json);
free(json);

}
int main()
{
printf(“hello world\n”);
Create_print();
return 0;
}


推荐阅读
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • Node.js学习笔记(一)package.json及cnpm
    本文介绍了Node.js中包的概念,以及如何使用包来统一管理具有相互依赖关系的模块。同时还介绍了NPM(Node Package Manager)的基本介绍和使用方法,以及如何通过NPM下载第三方模块。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了PhysioNet网站提供的生理信号处理工具箱WFDB Toolbox for Matlab的安装和使用方法。通过下载并添加到Matlab路径中或直接在Matlab中输入相关内容,即可完成安装。该工具箱提供了一系列函数,可以方便地处理生理信号数据。详细的安装和使用方法可以参考本文内容。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 第四章高阶函数(参数传递、高阶函数、lambda表达式)(python进阶)的讲解和应用
    本文主要讲解了第四章高阶函数(参数传递、高阶函数、lambda表达式)的相关知识,包括函数参数传递机制和赋值机制、引用传递的概念和应用、默认参数的定义和使用等内容。同时介绍了高阶函数和lambda表达式的概念,并给出了一些实例代码进行演示。对于想要进一步提升python编程能力的读者来说,本文将是一个不错的学习资料。 ... [详细]
  • 集成电路企业在进行跨隔离网数据交换时面临着安全性问题,传统的数据交换方式存在安全性堪忧、效率低下等问题。本文以《Ftrans跨网文件安全交换系统》为例,介绍了如何通过丰富的审批流程来满足企业的合规要求,保障数据交换的安全性。 ... [详细]
author-avatar
手机用户2502891985
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有