如何使用Arduino从HTTP响应正文中提取目标clientId字段值
Arduino MKR WiFi 1010 提取HTTP响应clientId字段实现方案
原有代码问题
- 嵌套if判断仅在匹配到分隔符后读取1个字符就终止读取,没有持续拉取后续正文内容,因此只能输出正文首字符
[。 - 换行符匹配顺序错误:标准HTTP响应的换行格式为
\r\n(先回车后换行),响应头与正文的分隔符为连续两组\r\n即\r\n\r\n,原有代码先匹配\n再匹配\r,逻辑顺序和标准格式不符,本身就无法正确定位正文起始位置。
实现思路
不要手动硬写字符串截取逻辑提取字段,稳定性极差,只要JSON格式出现空格、字段顺序变动就会失效。直接用成熟的ArduinoJson库完成解析即可,先在Arduino库管理器搜索ArduinoJson完成安装,之后按以下逻辑实现:
- 逐字符读取响应流,用状态计数的方式定位响应头结束位置,跳过所有响应头内容
- 将响应头之后的所有正文内容存入提前开辟的字符缓冲区,做好边界判断避免内存越界
- 调用ArduinoJson接口解析缓冲区里的JSON内容,直接读取目标字段值
可直接运行的参考代码
#include <ArduinoJson.h> // 响应缓冲区大小,当前响应长度仅241字节,开512字节留足冗余 const int RESP_BUF_SIZE = 512; char respBuf[RESP_BUF_SIZE]; int bufPos = 0; void loop() { if (client.connected() && client.available()) { bool headerFinished = false; int crlfCounter = 0; bufPos = 0; memset(respBuf, 0, RESP_BUF_SIZE); // 读取完整响应内容 while (client.available()) { char c = client.read(); if (!headerFinished) { // 计数连续换行符,累计到4个(\r\n\r\n)即判定响应头结束 if (c == '\r' || c == '\n') { crlfCounter++; } else { crlfCounter = 0; } if (crlfCounter == 4) { headerFinished = true; crlfCounter = 0; } } else { // 正文内容写入缓冲区,做边界判断避免越界 if (bufPos < RESP_BUF_SIZE - 1) { respBuf[bufPos++] = c; } } } // 解析JSON提取clientId StaticJsonDocument<512> jsonDoc; DeserializationError parseErr = deserializeJson(jsonDoc, respBuf); if (parseErr) { Serial.print("JSON解析错误: "); Serial.println(parseErr.c_str()); client.stop(); return; } // 响应根节点是数组,取第一个元素的clientId字段 const char* clientId = jsonDoc[0]["clientId"]; Serial.print("获取到clientId:"); Serial.println(clientId); // 后续业务逻辑直接使用clientId变量即可 // client.stop(); // 业务处理完成后按需关闭连接 } }
注意事项
- 如果后续接口返回的响应长度增加,同步调大
RESP_BUF_SIZE和StaticJsonDocument的传入参数即可,建议预留30%左右的冗余空间避免解析失败。 - 读取响应时不要加过长的延时,WiFi客户端的流数据如果不及时读取会被缓冲区丢弃,导致解析失败。
- 如果不需要保留其他响应字段,也可以不用存储完整正文,在定位到正文起始位置后直接把流传给
deserializeJson,能进一步节省内存。
内容的提问来源于stack exchange,提问作者hellooooo
相关产品推荐
相关产品推荐

