【花雕学编程】Arduino JSON 之处理 JSON 数组

在这里插入图片描述

Arduino是一个开放源码的电子原型平台,它可以让你用简单的硬件和软件来创建各种互动的项目。Arduino的核心是一个微控制器板,它可以通过一系列的引脚来连接各种传感器、执行器、显示器等外部设备。Arduino的编程是基于C/C++语言的,你可以使用Arduino IDE(集成开发环境)来编写、编译和上传代码到Arduino板上。Arduino还有一个丰富的库和社区,你可以利用它们来扩展Arduino的功能和学习Arduino的知识。

Arduino的特点是:
1、开放源码:Arduino的硬件和软件都是开放源码的,你可以自由地修改、复制和分享它们。
2、易用:Arduino的硬件和软件都是为初学者和非专业人士设计的,你可以轻松地上手和使用它们。
3、便宜:Arduino的硬件和软件都是非常经济的,你可以用很低的成本来实现你的想法。
4、多样:Arduino有多种型号和版本,你可以根据你的需要和喜好来选择合适的Arduino板。
5、创新:Arduino可以让你用电子的方式来表达你的创意和想象,你可以用Arduino来制作各种有趣和有用的项目,如机器人、智能家居、艺术装置等。

在这里插入图片描述
Arduino JSON 的全面详细科学解释

  1. Arduino 概述
    Arduino 是一个开源的电子原型平台,基于易用的硬件和软件。它由硬件(各种型号的 Arduino 板)和软件(Arduino IDE)组成,主要用于快速开发交互式项目。

  2. JSON 概述
    JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于 JavaScript 的一个子集,但独立于语言,广泛用于 Web 应用和 IoT 设备之间的数据交换。

  3. Arduino JSON 的定义
    Arduino JSON 是指在 Arduino 平台上使用 JSON 格式进行数据交换和处理。通过 Arduino JSON 库,开发者可以轻松地在 Arduino 项目中解析和生成 JSON 数据。Arduino JSON是一个用于处理JSON数据的Arduino库,适用于嵌入式C++项目。它支持JSON的序列化和反序列化,能够在有限的内存环境中高效地解析和生成JSON数据。

  4. 关键特点:
    简单的API:Arduino JSON提供了直观的语法,使开发者能够轻松地处理对象和数组。
    序列化和反序列化:支持将JSON数据转换为字符串(序列化)和将字符串转换为JSON数据(反序列化)。
    输入过滤:可以过滤大型输入,只保留与应用程序相关的字段,从而节省内存。
    流式处理:支持从输入流(如串行端口、以太网连接等)中解析JSON数据。
    缩进输出:可以生成紧凑的JSON文档或美化的JSON文档。
    闪存字符串:可以直接使用存储在程序内存中的字符串(PROGMEM)。
    字符串去重:去重JSON文档中的字符串,减少内存消耗。
    隐式或显式转换:支持两种编码风格,可以选择隐式或显式转换。

  5. 主要功能
    数据解析: 从 JSON 字符串中提取数据。
    数据生成: 将数据转换为 JSON 格式的字符串。
    数据交换: 通过 JSON 格式与外部服务进行数据交换。

  6. 技术实现
    库支持: 使用 Arduino JSON 库(如 ArduinoJson)来解析和生成 JSON 数据。
    数据格式: JSON 数据格式包括对象(用花括号 {} 表示)和数组(用方括号 [] 表示),键值对用冒号 : 分隔。
    数据处理: 在 Arduino 上处理 JSON 数据,执行相应操作。

  7. 应用场景
    物联网(IoT): 与云平台进行数据交换。
    Web 服务: 与 Web API 进行数据交互。
    传感器数据: 处理和传输传感器数据。
    配置文件: 存储和读取配置信息。

  8. 开发工具
    Arduino IDE: 编写和上传代码到 Arduino 板。
    ArduinoJson 库: 提供 JSON 解析和生成的库。
    网络模块: 如 ESP8266、ESP32,用于连接互联网。

  9. 优势与挑战
    优势:
    轻量级: JSON 格式简洁,易于解析和生成。
    跨平台: 独立于语言,适用于多种开发环境。
    灵活性: 支持复杂的数据结构。
    挑战:
    内存限制: Arduino 内存有限,处理大 JSON 数据需优化。
    性能限制: 解析和生成 JSON 数据可能占用较多资源。
    数据安全: 需要确保数据完整性和安全性。

  10. 未来发展方向
    优化性能: 提高 JSON 解析和生成的效率。
    扩展功能: 支持更多的 JSON 特性(如 JSON Schema)。
    增强安全性: 提供数据加密和验证机制。

在这里插入图片描述

主要特点
轻量级数据格式:JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,JSON 数组是 JSON 数据结构的一种形式,它以紧凑的格式表示一组有序的数据元素。在 Arduino 中处理 JSON 数组时,占用的内存空间相对较小,适合资源有限的微控制器。
易于解析和生成:Arduino 有专门的 JSON 库,如 ArduinoJson 库,它提供了简单易用的函数和方法,使得解析 JSON 数组以及将数据生成 JSON 数组变得较为容易。开发人员可以方便地通过数组索引或键值对的方式访问和操作 JSON 数组中的数据。
跨平台兼容性:JSON 是一种通用的数据格式,不受特定操作系统或编程语言的限制。这意味着 Arduino 与其他设备或平台进行数据交互时,使用 JSON 数组可以很方便地实现数据的共享和交换,无论对方是运行在 Windows、Linux 还是其他系统上的程序。
灵活性高:JSON 数组可以包含不同类型的数据,如数字、字符串、布尔值甚至其他 JSON 对象或数组。在 Arduino 项目中,这种灵活性使得它能够适应各种不同的数据结构和应用需求,可以根据实际情况动态地调整和扩展数据内容。

应用场景
传感器数据传输:在物联网项目中,Arduino 通常会连接多个传感器,传感器收集到的数据可以以 JSON 数组的形式进行打包和传输。例如,一个环境监测系统中,温度、湿度、光照等传感器的数据可以组成一个 JSON 数组,通过网络发送到服务器或其他设备进行存储和分析。
配置文件解析:Arduino 项目的配置信息可以存储在 JSON 格式的文件中。通过解析 JSON 数组,Arduino 可以读取配置文件中的各种参数,如网络连接设置、传感器校准值、设备运行模式等。这样可以方便地在不修改代码的情况下,通过修改配置文件来调整设备的行为。
与 Web 服务交互:当 Arduino 与 Web 服务进行通信时,JSON 数组是一种常见的数据交换格式。例如,Arduino 可以向云端服务器发送包含设备状态信息的 JSON 数组,也可以从服务器接收控制指令或其他数据以 JSON 数组形式返回的信息,实现设备与云端的双向数据交互。
数据记录和存储:在一些需要记录数据的应用中,如实验数据采集、工业生产数据监控等,Arduino 可以将采集到的数据以 JSON 数组的形式存储在外部存储设备中,如 SD 卡。这样便于后续对数据进行整理、分析和可视化处理。

注意事项
内存管理:虽然 JSON 数组本身是轻量级的,但在解析和处理大型 JSON 数组时,可能会占用较多的内存。Arduino 的内存资源有限,因此需要注意合理分配内存,避免内存溢出。可以通过优化代码,及时释放不再使用的内存空间,或者使用动态内存分配策略来解决内存问题。
数据类型匹配:在解析 JSON 数组时,要确保 Arduino 代码中定义的数据类型与 JSON 数组中实际的数据类型相匹配。例如,如果 JSON 数组中的某个元素是整数,那么在 Arduino 中使用相应的整数变量来接收该数据,否则可能会导致数据错误或程序异常。
错误处理:在解析 JSON 数组时,可能会遇到各种错误,如 JSON 格式错误、数据缺失等。因此,需要在代码中加入适当的错误处理机制,以便能够及时发现和处理这些错误,避免程序崩溃。可以使用 ArduinoJson 库提供的错误代码和相关函数来进行错误判断和处理。
网络传输稳定性:当通过网络传输 JSON 数组时,要考虑网络的稳定性和数据的完整性。可能会出现数据丢失、延迟或乱序等问题。可以采用一些网络协议和技术来保证数据的可靠传输,如 TCP 协议、添加校验和、重传机制等。
安全性:如果 JSON 数组中包含敏感信息,如用户密码、设备密钥等,需要对数据进行加密处理,以防止数据被窃取或篡改。可以使用加密算法对 JSON 数据进行加密和解密,确保数据的安全性。同时,在与外部设备或网络进行交互时,要注意防范网络攻击,如 SQL 注入、跨站脚本攻击等。

在这里插入图片描述
1、解析 JSON 数组

#include <ArduinoJson.h>
#include <Arduino.h>

const char* jsonString = 
  "[{\"name\":\"John\", \"age\":30},"
   "{\"name\":\"Jane\", \"age\":25},"
   "{\"name\":\"Doe\", \"age\":40}]";

void setup() {
  Serial.begin(9600);
  while (!Serial) continue;

  DynamicJsonDocument doc(1024);
  DeserializationError error = deserializeJson(doc, jsonString);

  if (error) {
    Serial.print("deserializeJson() failed: ");
    Serial.println(error.c_str());
    return;
  }

  JsonArray array = doc.as<JsonArray>();
  for (JsonObject obj : array) {
    Serial.print("Name: ");
    Serial.print(obj["name"]);
    Serial.print(", Age: ");
    Serial.println(obj["age"]);
  }
}

void loop() {
  // Nothing to do here
}

要点解读:
JSON 字符串解析:使用 deserializeJson 函数将 JSON 字符串解析为 DynamicJsonDocument 对象。
错误处理:检查 deserializeJson 的返回值,确保解析成功。
遍历 JSON 数组:通过 JsonArray 遍历数组中的每个 JsonObject,并访问其键值对。
动态内存分配:DynamicJsonDocument 的大小需要根据 JSON 数据的大小进行调整。

2、生成 JSON 数组

#include <ArduinoJson.h>
#include <Arduino.h>

void setup() {
  Serial.begin(9600);
  while (!Serial) continue;

  DynamicJsonDocument doc(1024);
  JsonArray array = doc.to<JsonArray>();

  JsonObject obj1 = array.createNestedObject();
  obj1["name"] = "John";
  obj1["age"] = 30;

  JsonObject obj2 = array.createNestedObject();
  obj2["name"] = "Jane";
  obj2["age"] = 25;

  JsonObject obj3 = array.createNestedObject();
  obj3["name"] = "Doe";
  obj3["age"] = 40;

  String jsonString;
  serializeJson(doc, jsonString);

  Serial.println(jsonString);
}

void loop() {
  // Nothing to do here
}

要点解读:
JSON 数组生成:使用 DynamicJsonDocument 创建一个 JSON 数组,并通过 createNestedObject 方法添加多个 JSON 对象。
序列化为字符串:使用 serializeJson 函数将 DynamicJsonDocument 对象序列化为 JSON 字符串。
动态内存分配:DynamicJsonDocument 的大小需要根据 JSON 数据的大小进行调整。
输出 JSON 字符串:通过串口输出生成的 JSON 字符串,便于调试和验证。

3、解析和生成 JSON 数组

#include <ArduinoJson.h>
#include <Arduino.h>

const char* jsonString = 
  "[{\"name\":\"John\", \"age\":30},"
   "{\"name\":\"Jane\", \"age\":25},"
   "{\"name\":\"Doe\", \"age\":40}]";

void setup() {
  Serial.begin(9600);
  while (!Serial) continue;

  // 解析 JSON 数组
  DynamicJsonDocument doc(1024);
  DeserializationError error = deserializeJson(doc, jsonString);

  if (error) {
    Serial.print("deserializeJson() failed: ");
    Serial.println(error.c_str());
    return;
  }

  JsonArray array = doc.as<JsonArray>();
  for (JsonObject obj : array) {
    Serial.print("Name: ");
    Serial.print(obj["name"]);
    Serial.print(", Age: ");
    Serial.println(obj["age"]);
  }

  // 生成新的 JSON 数组
  DynamicJsonDocument newDoc(1024);
  JsonArray newArray = newDoc.to<JsonArray>();

  for (JsonObject obj : array) {
    JsonObject newObj = newArray.createNestedObject();
    newObj["name"] = obj["name"];
    newObj["age"] = obj["age"] + 1; // 假设每个人都长了一岁
  }

  String newJsonString;
  serializeJson(newDoc, newJsonString);

  Serial.println(newJsonString);
}

void loop() {
  // Nothing to do here
}

要点解读:
解析和生成结合:先解析一个 JSON 数组,然后基于解析结果生成一个新的 JSON 数组。
数据处理:在生成新的 JSON 数组时,可以对数据进行处理,例如在本例中将每个人的年龄加1。
动态内存分配:DynamicJsonDocument 的大小需要根据 JSON 数据的大小进行调整。
错误处理:检查 deserializeJson 的返回值,确保解析成功。
输出 JSON 字符串:通过串口输出生成的 JSON 字符串,便于调试和验证。

在这里插入图片描述

4、解析传感器数据数组(接收端)

#include <ArduinoJson.h>

void parseSensorData(const char* json) {
  StaticJsonDocument<256> doc;
  DeserializationError error = deserializeJson(doc, json);

  if (error) {
    Serial.print(F("JSON解析失败: "));
    Serial.println(error.f_str());
    return;
  }

  // 提取传感器数组
  JsonArray sensors = doc["sensors"];
  
  Serial.println(F("当前传感器读数:"));
  for (JsonVariant sensor : sensors) {
    Serial.print(sensor["name"].as<const char*>());
    Serial.print(": ");
    Serial.print(sensor["value"].as<float>());
    Serial.println(sensor["unit"].as<const char*>());
  }
}

void setup() {
  Serial.begin(115200);
  
  // 模拟接收到的JSON数据
  const char* json = 
    "{\"sensors\":["
    "{\"name\":\"温度\",\"value\":25.5,\"unit\":\"°C\"},"
    "{\"name\":\"湿度\",\"value\":60.2,\"unit\":\"%\"},"
    "{\"name\":\"气压\",\"value\":1013.2,\"unit\":\"hPa\"}"
    "]}";
  
  parseSensorData(json);
}

void loop() {}

要点解读:

使用StaticJsonDocument固定内存分配避免碎片

JsonArray类型直接访问数组元素

JsonVariant遍历数组元素

安全类型转换(as())

错误处理机制

5、生成动态JSON数组(发送端)

#include <ArduinoJson.h>
#include <WiFi.h>

void sendSensorData() {
  DynamicJsonDocument doc(1024);
  JsonArray data = doc.createNestedArray("data");

  // 添加3组随机数据
  for (int i = 0; i < 3; i++) {
    JsonObject item = data.createNestedObject();
    item["id"] = i + 1;
    item["temp"] = random(200, 300) / 10.0;
    item["timestamp"] = millis();
  }

  // 序列化为字符串
  String output;
  serializeJson(doc, output);
  
  // 通过WiFi发送(示例)
  WiFiClient client;
  if (client.connect("api.example.com", 80)) {
    client.println("POST /data HTTP/1.1");
    client.println("Content-Type: application/json");
    client.print("Content-Length: ");
    client.println(output.length());
    client.println();
    client.println(output);
  }
}

void setup() {
  Serial.begin(115200);
  WiFi.begin("SSID", "password");
  sendSensorData();
}

void loop() {}

关键点:

createNestedArray()动态创建数组

createNestedObject()构建复杂结构

DynamicJsonDocument处理可变长度数据

自动类型转换(int/float/String)

网络传输前的序列化

6、过滤和修改数组数据

#include <ArduinoJson.h>

void filterThreshold() {
  const char* json = 
    "{\"readings\":["
    "{\"sensor\":\"A\",\"val\":12},"
    "{\"sensor\":\"B\",\"val\":25},"
    "{\"sensor\":\"C\",\"val\":8},"
    "{\"sensor\":\"D\",\"val\":30}"
    "]}";

  DynamicJsonDocument doc(256);
  deserializeJson(doc, json);

  JsonArray readings = doc["readings"];
  
  // 过滤阈值>10的数据
  for (int i = readings.size() - 1; i >= 0; i--) {
    if (readings[i]["val"] < 10) {
      readings.remove(i);
    }
  }

  // 添加平均计算
  float sum = 0;
  for (JsonVariant v : readings) {
    sum += v["val"];
  }
  doc["average"] = sum / readings.size();

  serializeJsonPretty(doc, Serial); // 美化输出
}

void setup() {
  Serial.begin(115200);
  filterThreshold();
}

void loop() {}

核心技术:

反向遍历避免删除导致的索引错位

remove()动态删除数组元素

动态添加新字段

数组数学计算

serializeJsonPretty格式化输出

注意,以上案例只是为了拓展思路,仅供参考。它们可能有错误、不适用或者无法编译。您的硬件平台、使用场景和Arduino版本可能影响使用方法的选择。实际编程时,您要根据自己的硬件配置、使用场景和具体需求进行调整,并多次实际测试。您还要正确连接硬件,了解所用传感器和设备的规范和特性。涉及硬件操作的代码,您要在使用前确认引脚和电平等参数的正确性和安全性。

在这里插入图片描述

「雕爷编程Arduino动手做寻迹的实验可以使用TCRT5000红外反射光电开关寻迹传感器模块。这个传感器模块可以通过检测周围的光反射来进行寻迹操作。你可以将这个模块连接到mBot的主控板mCore V1.5的RJ25接口上,因为mBot的主控板兼容Arduino系统,所以你可以使用Arduino编程语言来控制mBot进行寻迹操作。请参考【Arduino】168种传感器模块系列实验中的实验六十六,该实验详细介绍了如何使用TCRT5000红外反射光电开关寻迹传感器模块进行寻迹。祝你成功完成实验!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [【雕爷编程Arduino动手做(194)---makeblock mbot 主控板2](https://blog.youkuaiyun.com/weixin_41659040/article/details/132141677)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *3* [【雕爷编程Arduino动手做(65)---红外寻迹传感器](https://blog.youkuaiyun.com/weixin_41659040/article/details/106604080)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

驴友花雕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值