1. 程式人生 > >博哥玩物聯網系列2-ArduinoJson庫

博哥玩物聯網系列2-ArduinoJson庫

一、前言
在上一篇中,介紹了一下ESP8266 wifi模組(http://www.arduino.cn/thread-44963-1-1.html)的基本使用。而對於任何物聯網IOT來說,基本上都免不了雲平臺的Json字元解析。好在Arduino資料夠多,在github上找到了關於Json解析的庫。今天就開始對Json進行介紹以及對ArduinoJson庫進行介紹如何使用。
      庫在github上的連結地址為:https://github.com/bblanchon/ArduinoJson
      庫的英文介紹連結地址為:https://bblanchon.github.io/ArduinoJson/doc/

      下載完庫之後,包含以下標頭檔案就可以還是使用了。
#include <ArduinoJson.h>
      那麼,接下來就開始本篇的重點了。


二、JSON基礎介紹

       2.1 什麼是Json?
Json 指的是JavaScript物件表示法(JavaScript Object Notation)。
              Json 是輕量級的文字資料交換格式,類似於XML,比XML更小、更快,更容易解析。
              Json 獨立於語言。
              Json 具有自我描述性,容易理解。

2.2 具體使用例子
例子1:

[C] 純文字檢視

 複製程式碼

?

程式碼

001

002

003

004

005

006

007

008

009

{

"motor": {

"left": 100,

"right": 20

},

"servo": {

"servo_1": 90

}

}

        表示這裡分別有兩個物件(物件是用{}區分),物件分別是motor、servo。
        對於物件motor來說,有兩個欄位 left 和 right,它們的值型別是int型,值分別是100和20;           

        對於物件servo來說,有一個欄位servo_1,它的值型別是int型,值是90。
        其實這就相當於 Key:value。


        例子2:

[C] 純文字檢視 複製程式碼

?

程式碼

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

{

"employees": [

{

"firstName": "Bill",

"lastName": "Gates"

},

{

"firstName": "George",

"lastName": "Bush"

},

{

"firstName": "Thomas",

"lastName": "Carter"

}

]

}


      表示這裡有一個物件陣列(陣列用[]區分)employees。
     每個物件裡面有兩個欄位firstName和lastName,它們的值型別都是String。

三、ArduinoJson庫介紹

      有了上面基礎,那麼我們就來講解一下ArduinoJson庫(裡面的具體原始碼我並沒有去研究,針對於使用),在寫程式碼之前,請把ArduinoJson庫放入Arduino library去,然後加入以下標頭檔案:
#include <ArduinoJson.h>

      3.1 如何去生成一個Json字串
           比如,我們需要生成如下Json字串:

[C] 純文字檢視 複製程式碼

?

程式碼

001

002

003

004

005

006

007

008

{

"sensor": "gps",

"time": 1351824120,

"data": [

48.75608,

2.302038

]

}


         程式碼如下:
         

[C] 純文字檢視 複製程式碼

?

程式碼

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

017

018

019

020

021

022

023

024

025

026

027

028

029

030

031

032

033

034

035

036

037

038

039

040

041

042

043

044

045

046

047

048

049

050

051

052

053

054

055

056

057

058

059

060

061

/*

*日期:2017/04/22

*功能:建立Json字串

*作者:微控制器菜鳥

*{

*  "sensor": "gps",

*  "time": 1351824120,

*  "data": [

*     48.756080,

*     2.302038

*   ]

* }

*/

#include <ArduinoJson.h>

void setup() {

Serial.begin(9600);

while (!Serial) {

// wait serial port initialization

}

// Json物件物件樹的記憶體工具 靜態buffer

// 200 是大小 如果這個Json物件更加複雜,那麼就需要根據需要去增加這個值.

StaticJsonBuffer<200> jsonBuffer;

// StaticJsonBuffer 在棧區分配記憶體   它也可以被 DynamicJsonBuffer(記憶體在堆區分配) 代替

// DynamicJsonBuffer  jsonBuffer;

//建立根,也就是頂節點

JsonObject& root = jsonBuffer.createObject();

root["sensor"] = "gps";//設定sensor(key):"gps"(value)

root["time"] = 1351824120;//設定time(key):"1351824120"(value)

// 新增一個data陣列

JsonArray& data = root.createNestedArray("data");

data.add(double_with_n_digits(48.756080, 6));

//如果直接寫成  data.add(48.756080); 保留2位小數

//上面的語句也可以寫成 data.add(48.756080,6); 保留6位小數

data.add(double_with_n_digits(2.302038, 6));

root.printTo(Serial);//單行列印

// This prints:

// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}

Serial.println();

root.prettyPrintTo(Serial);//多行列印

// This prints:

// {

//   "sensor": "gps",

//   "time": 1351824120,

//   "data": [

//     48.756080,

//     2.302038

//   ]

// }

}

void loop() {

// not used in this example

}

   
        執行結果:
          

        那麼問題來了?
        問題1:StaticJsonBuffer 和 DynamicJsonBuffer  區別在哪裡?
        答:詳情可以參考 http://bblanchon.github.io/Ardui ... -dynamicjsonbuffer/
                
               我個人的理解是:StaticJsonBuffer好比是靜態程式碼區,DynamicJsonBuffer好比是RAM區,對於Arduino來說,建議使用StaticJsonBuffer。
        問題2:如何去決定這個buffer的大小?
        答:參考 http://bblanchon.github.io/Ardui ... ne-the-buffer-size/
               
      3.2 如何去解析一個Json字串
       上面說到,我們如何去建立一個Json字串,那麼反過來,要怎麼解析呢?
        直接上程式碼:

[C] 純文字檢視 複製程式碼

?

程式碼

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

017

018

019

020

021

022

023

024

025

026

027

028

029

030

031

032

033

034

035

036

037

038

039

040

041

042

043

044

045

046

047

048

049

050

051

052

053

054

055

056

057

058

059

060

061

/*

*日期:2017/04/22

*功能:解析Json字串

*作者:微控制器菜鳥

*{

*  "sensor": "gps",

*  "time": 1351824120,

*  "data": [

*     48.756080,

*     2.302038

*   ]

* }

*/

#include <ArduinoJson.h>

void setup() {

Serial.begin(9600);

while (!Serial) {

// wait serial port initialization

}

// Json物件物件樹的記憶體工具 靜態buffer

// 200 是大小 如果這個Json物件更加複雜,那麼就需要根據需要去增加這個值.

StaticJsonBuffer<200> jsonBuffer;

// JSON input string.

//

// It's better to use a char[] as shown here.

// If you use a const char* or a String, ArduinoJson will

// have to make a copy of the input in the JsonBuffer.

char json[] =

"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";

//建立根,也就是頂節點 然後把Json字串扔進去  由於是物件 所以我們用parseObject

//如果是陣列 用 JsonArray& root = jsonBuffer.parseArray(json);

//注意:

JsonObject& root = jsonBuffer.parseObject(json);

// 判斷是否解析成功

if (!root.success()) {

Serial.println("parseObject() failed");

return;

}

//開始獲得每個物件

const char* sensor = root["sensor"];

long time = root["time"];

double latitude = root["data"][0];

double longitude = root["data"][1];

// Print values.

Serial.println(sensor);

Serial.println(time);

Serial.println(latitude, 6);

Serial.println(longitude, 6);

}

void loop() {

// not used in this example

}



        效果:
        

       注意點1:parseObject()是以char*作為引數的,並不是const char*。原因是庫原始碼會對這塊記憶體進行修改(在字串的末尾加入\0,把空格轉成\n or \t)。
       注意點2:JsonObject.success()用來判斷是否解析成功。
                       解析失敗通常有如下三個原因:
                       原因1:Json字串非法(格式不對);
                       原因2:Json字串產生物件
                       原因3:StaticJsonBuffer太小了

        參考:https://bblanchon.github.io/ArduinoJson/doc/decoding/
                     

四、總結        總體上,Json屬於一種資料交換格式,不會說太難。本篇屬於簡單介紹了ArduinoJson庫的使用,更加複雜的使用請直接去到ArduinoJson的主頁去查閱。