Thư viện ArduinoJson: tạo & parse JSON trên Arduino/ESP32
ArduinoJson là thư viện JSON cho Arduino mạnh và phổ biến nhất, do Benoît Blanchon viết. Bạn dùng nó mỗi khi ESP32 nói chuyện với API HTTP, MQTT, hay đọc cấu hình từ SD card. Bài này hướng dẫn từ v6/v7 API mới, gồm tạo, parse, lưu vào file, và các lỗi memory thường gặp.
1. Cài đặt
Library Manager → tìm "ArduinoJson" by Benoit Blanchon. Chọn phiên bản 7.x mới nhất (API gọn hơn v6).
#include
2. Tạo JSON — Serialize
JsonDocument doc;
doc["device"] = "esp32-sensor-01";
doc["temp"] = 25.4;
doc["hum"] = 67;
doc["online"] = true;
JsonArray relays = doc["relays"].to();
relays.add(0);
relays.add(1);
relays.add(0);
String output;
serializeJson(doc, output);
Serial.println(output);
// {"device":"esp32-sensor-01","temp":25.4,"hum":67,"online":true,"relays":[0,1,0]}
Hoặc xuất đẹp có thụt lề:
serializeJsonPretty(doc, Serial);
3. Parse JSON — Deserialize
const char* json = "{\"temp\":25.5,\"hum\":60,\"name\":\"phong-khach\"}";
JsonDocument doc;
DeserializationError err = deserializeJson(doc, json);
if (err) {
Serial.print("JSON loi: "); Serial.println(err.c_str());
return;
}
float t = doc["temp"];
int h = doc["hum"];
const char* name = doc["name"];
Serial.println(t);
Serial.println(name);
4. v7 vs v6 — khác biệt
v6 yêu cầu khai báo kích thước trước: StaticJsonDocument<256> hoặc DynamicJsonDocument(1024). v7 bỏ hết — chỉ cần JsonDocument doc;. Memory được cấp phát từ heap theo nhu cầu.
Nếu dùng v6 cũ, ước tính kích thước bằng ArduinoJson Assistant online.
5. Đọc mảng và đối tượng lồng nhau
const char* j = "{\"users\":[{\"id\":1,\"name\":\"An\"},{\"id\":2,\"name\":\"Binh\"}]}";
JsonDocument doc;
deserializeJson(doc, j);
for (JsonObject u : doc["users"].as()) {
int id = u["id"];
const char* name = u["name"];
Serial.print(id); Serial.print(" "); Serial.println(name);
}
6. Parse trực tiếp từ Stream (WiFiClient, File)
Tiết kiệm RAM cực mạnh khi đọc HTTP response hoặc file SD lớn:
HTTPClient http;
http.begin("https://api.example.com/data");
int code = http.GET();
if (code == 200) {
JsonDocument doc;
deserializeJson(doc, http.getStream()); // stream trực tiếp
// ...
}
http.end();
File f = SD.open("/config.json");
JsonDocument doc;
deserializeJson(doc, f);
f.close();
7. Filter — chỉ lấy field cần thiết
API trả về JSON 50KB nhưng bạn chỉ cần 3 field — dùng filter để giảm RAM:
JsonDocument filter;
filter["name"] = true;
filter["temp"] = true;
JsonDocument doc;
deserializeJson(doc, stream, DeserializationOption::Filter(filter));
8. Kiểm tra field tồn tại
if (doc["optional"].is()) {
int v = doc["optional"];
}
// hoặc fallback:
int v = doc["optional"] | 0; // 0 nếu thiếu
9. Memory — lỗi #1 với ArduinoJson
- JSON quá lớn →
NoMemory. Trên Uno (2KB RAM) chỉ xử lý được JSON nhỏ. Lên ESP32 (320KB RAM) thoải mái. - Trả về
const char*từ JsonDocument là pointer vào buffer trong doc. Khidocbị huỷ (ra khỏi scope), pointer thành dangling. Nếu cần giữ, copy sangString:String name = doc["name"].as(); - Không bao giờ
strcpy()từ const char* JSON sang buffer mà không kiểm tra strlen.
10. Bảng nhanh các API hay dùng
| Hàm | Vai trò |
|---|---|
deserializeJson(doc, src) | Parse từ String/char*/Stream/File |
serializeJson(doc, dst) | Xuất compact |
serializeJsonPretty(doc, dst) | Xuất có thụt lề |
doc.to<JsonArray>() | Khởi tạo mảng |
doc["k"].is<T>() | Check kiểu |
doc.size() | Số phần tử (object/array) |
doc.memoryUsage() | RAM đã dùng (v6) / không có v7 |
Liên quan
Dùng cùng PubSubClient: subscribe/publish MQTT để truyền JSON qua MQTT. Hoặc xem dự án ESP32 gửi data lên ThingSpeak.