您的位置:首页 > Web前端 > JavaScript

【ESP8266】使用ESP8266 NONOS SDK的JSON API

2016-03-17 10:27 555 查看

2016年9月30日更新:本人移植了cJSON到ESP8266的NONOS SDK,详情可以查看这篇文章:

http://blog.csdn.net/yannanxiu/article/details/52713746

===============================================

一、概述

这篇文章是讲解如何用ESP8266官方提供的Json接口处理数据。

首先要在esp_iot_sdk/example/IoT_Demo示例目录下找到user_json.cuser_json.h,把这两个文件包含进自己的工程。

查看json.h文件,里面有一下宏定义

#define JSON_TYPE_ARRAY '['
#define JSON_TYPE_OBJECT '{'
#define JSON_TYPE_PAIR ':'
#define JSON_TYPE_PAIR_NAME 'N' /* for N:V pairs */
#define JSON_TYPE_STRING '"'
#define JSON_TYPE_INT 'I'
#define JSON_TYPE_NUMBER '0'
#define JSON_TYPE_ERROR 0


后面的例程都是用此宏定义来判断Json的键值的数据类型。

二、生成一个Json

下面给出生成Json树的示例,生成的JSON树get_h内容如下:"hi":{"hello":"world"}

/***************************************************/
LOCAL int ICACHE_FLASH_ATTR
hello_get(struct jsontree_context *js_ctx)
{
const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1);
char string[32];

if (os_strncmp(path, "hello", 5) == 0) {
os_sprintf(string, "world");
}

jsontree_write_string(js_ctx, string);

return 0;
}

LOCAL struct jsontree_callback hello_callback =
JSONTREE_CALLBACK(hello_get, NULL);

JSONTREE_OBJECT(get_hello,
JSONTREE_PAIR("hello", &hello_callback));
JSONTREE_OBJECT(get_h,
JSONTREE_PAIR("hi", &get_hello));


其中宏定义JSONTREE_OBJECT是生成一个JSON数的对象,第一个参数是该对象的名称(get_h),JSONTREE_PAIR是生成一个键值对的宏。

JSONTREE_CALLBACL是生成一个回调指针的宏,该宏有两个参数,第一个参数是设置读取JSON树的值的函数,这里为hello_get函数,第二个参数是设置写入JSON树的值的函数,这里没有用到,为NULL。

hello_get是生成JSON树的值的函数。其中用os_strncnp进行Json键的判断,如果键为hello,则对该键写入"world"值。

这里生成的JSON是:"hi":{"hello","world"},hi是用来调用后面Json数据的:

#define BUF_LENTH 64
LOCAL char buf[BUF_LENTH];
json_ws_send((struct jsontree_value *)&get_h, "hi", buf);
os_printf("%s\n",buf);


使用json_ws_send函数可以把hi后面的数据写入buf,json_ws_send函数在IoT_demo例程中的user_json.c文件里。

最后打印结果是:

{

"hello":"world"

}

三、生成一个温湿度Json数据

下面是一个生成温湿度的例程:

/********************DHT11***********************/
LOCAL int ICACHE_FLASH_ATTR
dht11_get(struct jsontree_context *js_ctx)
{
const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1);
char string[32];

if (os_strncmp(path, "temp", 4) == 0)
{
//os_sprintf(string, "%d",temperture);
os_sprintf(string,"25");
}
else if(os_strncmp(path, "hum", 3) == 0)
{
//os_sprintf(string, "%d",hum);
os_sprintf(string,"40");
}

jsontree_write_string(js_ctx, string);

return 0;
}

LOCAL struct jsontree_callback dht11_callback =
JSONTREE_CALLBACK(dht11_get, NULL);

JSONTREE_OBJECT(get_dht11,
JSONTREE_PAIR("temp", &dht11_callback),
JSONTREE_PAIR("hum", &dht11_callback));
JSONTREE_OBJECT(DHT11JSON,
JSONTREE_PAIR("dht11", &get_dht11));

//返回DHT11数据的json格式
char* ICACHE_FLASH_ATTR
get_dht11_json(void)
{
static char dht11_buf[64];
os_memset(dht11_buf,0,64);		//清空
json_ws_send((struct jsontree_value *)&DHT11JSON, "dht11", dht11_buf);
return dht11_buf;
}


之后在user_init入口函数写一个打印函数

os_printf(get_dht11_json());


就可以看到串口打印出

{

"temp":"25",

"hum":"40"

}

四、一个完整的生成Json数据示例

下面是一个完整的生成Json数据的示例,可以生成字符串、整型值、数组、Json对象的Value。

Json数据的生成最重要的是理解函数回调机制,看代码要从下往上看,如果看官接触过异步回调机制的代码,阅读起来可能会有一种相似的感觉。

#include "user_json.h"
#include "ets_sys.h"
#include "os_type.h"
#include "osapi.h"
#include "mem.h"
#include "user_interface.h"

LOCAL int ICACHE_FLASH_ATTR
jsonTree_get(struct jsontree_context *js_ctx)
{
const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1);

//生成"String":"data"
if (os_strncmp(path, "String", os_strlen("String")) == 0) {
jsontree_write_string(js_ctx, "data");
//生成"Integer":1
} else if (os_strncmp(path, "Integer", os_strlen("Integer")) == 0) {
jsontree_write_int(js_ctx, 1);
//生成"Array":[0,1,2]
} else if (os_strncmp(path, "Array", os_strlen("Array")) == 0) {
int array[3] = {0,1,2};
jsontree_write_atom(js_ctx, "[");
jsontree_write_int_array(js_ctx, array, 3);
jsontree_write_atom(js_ctx, "]");
}

return 0;
}

LOCAL int ICACHE_FLASH_ATTR
jsonArray_get(struct jsontree_context *js_ctx)
{
const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1);

if (os_strncmp(path, "K1", os_strlen("K2")) == 0) {
jsontree_write_string(js_ctx, "D1");
} else if (os_strncmp(path, "K2", os_strlen("K2")) == 0) {
jsontree_write_string(js_ctx, "D2");
} else if (os_strncmp(path, "K3", os_strlen("K3")) == 0) {
jsontree_write_string(js_ctx, "D3");
}

return 0;
}

//初始化一个Json数据回调函数
//JSONTREE_CALLBACK第一个参数为生成Json数据的函数指针,第二个为获取Json数据的函数指针
LOCAL struct jsontree_callback jsonArrayCallback =
JSONTREE_CALLBACK(jsonArray_get, NULL);

JSONTREE_OBJECT(jsonArrayData,
JSONTREE_PAIR("K1", &jsonArrayCallback),
JSONTREE_PAIR("K2", &jsonArrayCallback),
JSONTREE_PAIR("K3", &jsonArrayCallback));
JSONTREE_ARRAY(jsonArray,
JSONTREE_PAIR_ARRAY(&jsonArrayData),
JSONTREE_PAIR_ARRAY(&jsonArrayData),
JSONTREE_PAIR_ARRAY(&jsonArrayData));

LOCAL struct jsontree_callback jsonCallback =
JSONTREE_CALLBACK(jsonTree_get, NULL);

JSONTREE_OBJECT(jsonObject,
JSONTREE_PAIR("String", &jsonCallback),
JSONTREE_PAIR("Integer", &jsonCallback),
JSONTREE_PAIR("JsonArray", &jsonArray));
JSONTREE_OBJECT(jsonTestTrees,
JSONTREE_PAIR("String", &jsonCallback),    //生成一个String键,并设置一个回调函数
JSONTREE_PAIR("Integer", &jsonCallback),   //生成一个Integer键,并设置一个回调函数
JSONTREE_PAIR("Array", &jsonCallback),     //生成一个Array键,并设置一个回调函数
JSONTREE_PAIR("JsonObject", &jsonObject)); //生成一个jsonObject键,并设置一个Json对象
JSONTREE_OBJECT(jsonTestTree,
JSONTREE_PAIR("jsonTest", &jsonTestTrees));

#define LENGTH 512
char* getJsonTree(void)
{
static char jsonbuf[LENGTH];
os_memset(jsonbuf, 0, LENGTH);      //初始化字符串
json_ws_send((struct jsontree_value *)&jsonTestTree, "jsonTest", jsonbuf);

//os_printf("%s\n", jsonbuf);

return jsonbuf;
}


该代码会生成如下Json数据:

{
"String": "data",
"Integer": 1,
"Array": [
0,
1,
2
],
"JsonObject": {
"String": "data",
"Integer": 1,
"JsonArray": [
{
"K1": "D1",
"K2": "D2",
"K3": "D3"
},
{
"K1": "D1",
"K2": "D2",
"K3": "D3"
},
{
"K1": "D1",
"K2": "D2",
"K3": "D3"
}
]
}
}


五、从Json提取数据

如果网络发送一串JSON数据给ESP8266,如何使用该接口获取JSON的键值呢?下面给出示例代码,这里使用的数据是上面生成的数据。

其中第二次的Json对象数据获取很麻烦,所以传给8266的Json尽量用一层,如果是数组里面再有Json对象,那么就更麻烦了,具体请看代码。

LOCAL int ICACHE_FLASH_ATTR
jsonTree_set(struct jsontree_context *js_ctx, struct jsonparse_state *parser)
{
int type;

while ((type = jsonparse_next(parser)) != 0) {
//如果是KEY类型
if (type == JSON_TYPE_PAIR_NAME) {
char buffer[64];
os_bzero(buffer, 64);

if (jsonparse_strcmp_value(parser, "String") == 0) {
jsonparse_next(parser);	//返回的是冒号字符
type = jsonparse_next(parser);	//返回的是双引号字符
os_printf("String Value type = %c\n", type);	// = "

//如果Value是字符串类型,则读取数据到buffer
if (JSON_TYPE_STRING == type){	//#define JSON_TYPE_STRING '"'
jsonparse_copy_value(parser, buffer, sizeof(buffer));
os_printf("String Value = %s\n", buffer);
}

} else if (jsonparse_strcmp_value(parser, "Integer") == 0) {
jsonparse_next(parser);
type = jsonparse_next(parser);

os_printf("Integer Value type = %c\n", type);	// = 0
//如果Value是数值类型
if(JSON_TYPE_NUMBER == type){	//#define JSON_TYPE_NUMBER '0'
//jsonparse_copy_value(parser, buffer, sizeof(buffer));
int num = 0;
num = jsonparse_get_value_as_int(parser);
os_printf("Integer Value = %d\n", num);		// = 1
}
} else if (jsonparse_strcmp_value(parser, "Array") == 0) {
jsonparse_next(parser);	//跳过冒号
type = jsonparse_next(parser);
os_printf("Array Value type = %c\n", type);		// = [

//如果Value是数组类型
if(JSON_TYPE_ARRAY == type){	//#define JSON_TYPE_ARRAY '['
//jsonparse_copy_value(parser, buffer, sizeof(buffer));
int length = jsonparse_get_len(parser);
os_printf("Array Length = %d\n", length);	//= 5, 数据是[0,1,2],可能把逗号也算在内

int i;
int num = 100;
//循环读取数组的数据
for(i=0; i<length; i++){
type = jsonparse_next(parser);
// 如果是逗号,则直接打印, 如果是数值则打印0
os_printf("Array[%d] type = %c ", i, type);

//如果是数值类型,则转换成int并打印出来
if(JSON_TYPE_NUMBER==type){
num = jsonparse_get_value_as_int(parser);
os_printf("Array[%d] = %d\n", i, num);
}
//后面可以添加else if判断是否是其他类型
//比如 else if(JSON_TYPE_OBJECT==type),判断是否是Json对象
else{
os_printf("\n");
}
}
}
}
#if 1
else if (jsonparse_strcmp_value(parser, "JsonObject") == 0) {
jsonparse_next(parser);	//跳过冒号
type = jsonparse_next(parser);
os_printf("JsonObject Value type = %c\n", type);		// = {

if(JSON_TYPE_OBJECT == type){	//#define JSON_TYPE_OBJECT '{'
int length = jsonparse_get_len(parser);
os_printf("JsonObject Length = %d\n", length);

//char temp[128] = {0};
//jsonparse_copy_value(parser, temp, 128);
//os_printf("JsonObject Value = %s\n", temp);

//循环读取数据
int i = 0;
//for(i=0; i<length; i++){
while(type != '}'){
i++;
type = jsonparse_next(parser);

os_printf("JsonObject[%d] type = %c", i, type);
os_printf("\n");
//os_memset(temp, 0, 128);
//jsonparse_copy_value(parser, temp, 128);
//os_printf("JsonObject Value = %s\n", temp);
//读取第二层的Json对象的数据
jsonObject_set(parser);
}
}

}
#endif
}
}

return 0;
}

LOCAL int ICACHE_FLASH_ATTR
jsonObject_set(struct jsonparse_state *parser)
{
int type = jsonparse_get_type(parser);
int vtype = parser->vtype;
//os_printf("json Object type=%c, vtype=%c\n", type, vtype);
char buffer[64];
os_bzero(buffer, 64);

//如果是KEY类型
if (vtype == JSON_TYPE_PAIR_NAME) {
if (jsonparse_strcmp_value(parser, "String") == 0) {
jsonparse_next(parser);	//返回的是冒号字符
type = jsonparse_next(parser);	//返回的是双引号字符
//os_printf("jsonObject String Value type = %c\n", type);	// = "

//如果Value是字符串类型,则读取数据到buffer
if (JSON_TYPE_STRING == type){	//#define JSON_TYPE_STRING '"'
jsonparse_copy_value(parser, buffer, sizeof(buffer));
os_printf("jsonObject String Value = %s\n", buffer);
}

} else if (jsonparse_strcmp_value(parser, "Integer") == 0) {
jsonparse_next(parser);
type = jsonparse_next(parser);
//os_printf("jsonObject Integer Value type = %c\n", type);	// = 0
//如果Value是数值类型
if(JSON_TYPE_NUMBER == type){	//#define JSON_TYPE_NUMBER '0'
//jsonparse_copy_value(parser, buffer, sizeof(buffer));
int num = 0;
num = jsonparse_get_value_as_int(parser);
os_printf("jsonObject Integer Value = %d\n", num);		// = 1
}
} else if (jsonparse_strcmp_value(parser, "JsonArray") == 0) {
jsonparse_next(parser);
type = jsonparse_next(parser);
//os_printf("jsonObject Integer Value type = %c\n", type);	// = 0
//如果Value是数值类型
if(JSON_TYPE_ARRAY == type){
//jsonparse_copy_value(parser, buffer, sizeof(buffer));
//os_printf("buffer = %s\n", buffer);
int length = jsonparse_get_len(parser);
os_printf("JsonArray Length = %d\n", length);	//读取出来的长度不准确

//循环读取Json对象数据
int i = 0;
//for(i=0; i<length; i++){
while(type != ']'){i++;		//用']'判断是否达到数组末尾

type = jsonparse_next(parser);

os_printf("JsonArray[%d] type = %c", i, type);
os_printf("\n");

//如果是KEY类型
if (type == JSON_TYPE_PAIR_NAME) {
if (jsonparse_strcmp_value(parser, "K1") == 0) {
jsonparse_next(parser);	//返回的是冒号字符
type = jsonparse_next(parser);	//返回的是双引号字符
//os_printf("K1 Value type = %c\n", type);	// = "

//如果Value是字符串类型,则读取数据到buffer
if (JSON_TYPE_STRING == type){	//#define JSON_TYPE_STRING '"'
os_bzero(buffer, 64);
jsonparse_copy_value(parser, buffer, sizeof(buffer));
os_printf("K1 = %s\n", buffer);
}
} else if(jsonparse_strcmp_value(parser, "K2") == 0){
jsonparse_next(parser);	//返回的是冒号字符
type = jsonparse_next(parser);	//返回的是双引号字符
//如果Value是字符串类型,则读取数据到buffer
if (JSON_TYPE_STRING == type){	//#define JSON_TYPE_STRING '"'
os_bzero(buffer, 64);
jsonparse_copy_value(parser, buffer, sizeof(buffer));
os_printf("K2 = %s\n", buffer);
}
} else if(jsonparse_strcmp_value(parser, "K3") == 0){
jsonparse_next(parser);	//返回的是冒号字符
type = jsonparse_next(parser);	//返回的是双引号字符
//如果Value是字符串类型,则读取数据到buffer
if (JSON_TYPE_STRING == type){	//#define JSON_TYPE_STRING '"'
os_bzero(buffer, 64);
jsonparse_copy_value(parser, buffer, sizeof(buffer));
os_printf("K3 = %s\n", buffer);
}
}
}
}
}
}
}
}

LOCAL int ICACHE_FLASH_ATTR
jsonArray_set(struct jsontree_context *js_ctx, struct jsonparse_state *parser)
{
int type;

while ((type = jsonparse_next(parser)) == 0) {
//如果是KEY类型
if (type == JSON_TYPE_PAIR_NAME) {
char buffer[64];
os_bzero(buffer, 64);

if (jsonparse_strcmp_value(parser, "K1") == 0) {
if (JSON_TYPE_STRING == type){	//#define JSON_TYPE_STRING '"'
jsonparse_copy_value(parser, buffer, sizeof(buffer));
os_printf("K1 Value = %s\n", buffer);
}
} else if (jsonparse_strcmp_value(parser, "K2")==0) {
if (JSON_TYPE_STRING == type){	//#define JSON_TYPE_STRING '"'
jsonparse_copy_value(parser, buffer, sizeof(buffer));
os_printf("K2 Value = %s\n", buffer);
}
} else if (jsonparse_strcmp_value(parser, "K3")==0) {
if (JSON_TYPE_STRING == type){	//#define JSON_TYPE_STRING '"'
jsonparse_copy_value(parser, buffer, sizeof(buffer));
os_printf("K3 Value = %s\n", buffer);
}
}
}
}

return 0;
}

void ICACHE_FLASH_ATTR
setJsonTree(char *json)
{
struct jsontree_context js;

jsontree_setup(&js, (struct jsontree_value *)&jsonTestTree, json_putchar);
json_parse(&js, json);
}

void ICACHE_FLASH_ATTR
setJsonObject(char *json)
{
struct jsontree_context js;

jsontree_setup(&js, (struct jsontree_value *)&jsonObject, json_putchar);
json_parse(&js, json);
}


最后要修改一下这条语句,给jsonCallback第二个参数添加jsonTree_set。

LOCAL struct jsontree_callback jsonCallback =
JSONTREE_CALLBACK(jsonTree_get, jsonTree_set);


打印:

String Value type = "

String Value = data

Integer Value type = 0

Integer Value = 1

Array Value type = [

Array Length = 5

Array[0] type = 0 Array[0] = 0

Array[1] type = , 

Array[2] type = 0 Array[2] = 1

Array[3] type = , 

Array[4] type = 0 Array[4] = 2

JsonObject Value type = {

JsonObject Length = 10

JsonObject[1] type = N

jsonObject String Value = data

JsonObject[2] type = ,

JsonObject[3] type = N

jsonObject Integer Value = 1

JsonObject[4] type = ,

JsonObject[5] type = N

JsonArray Length = 9

JsonArray[1] type = {

JsonArray[2] type = N

K1 = D1

JsonArray[3] type = ,

JsonArray[4] type = N

K2 = D2

JsonArray[5] type = ,

JsonArray[6] type = N

K3 = D3

JsonArray[7] type = }

JsonArray[8] type = ,

JsonArray[9] type = {

JsonArray[10] type = N

K1 = D1

JsonArray[11] type = ,

JsonArray[12] type = N

K2 = D2

JsonArray[13] type = ,

JsonArray[14] type = N

K3 = D3

JsonArray[15] type = }

JsonArray[16] type = ,

JsonArray[17] type = {

JsonArray[18] type = N

K1 = D1

JsonArray[19] type = ,

JsonArray[20] type = N

K2 = D2

JsonArray[21] type = ,

JsonArray[22] type = N

K3 = D3

JsonArray[23] type = }

JsonArray[24] type = ]

JsonObject[6] type = }

六、代码下载

如果想要示例代码,可以从这里下载:http://download.csdn.net/detail/u012163234/9638834




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: