如何在ESP32的SPIFFS中用ArduinoJson6存储多个SSID与密码
问题描述
目标是在ESP32的SPIFFS中使用ArduinoJson6存储多组SSID和密码,此前尝试直接追加文件或读取文档、删除文件后重新序列化保存的方式,均无法得到预期的JSON结构。
预期JSON结构
{"information":[ { "SSID":"variable blaat1", "PASS":"variable Abc1", "NUMBER": "1" }, { "SSID":"variable blaat2", "PASS":"variable Abc2", "NUMBER": "2" }, { "SSID":"variable blaat3", "PASS":"variable Abc3", "NUMBER": "3" }, { "SSID":"variable blaat4", "PASS":"variable Abc4", "NUMBER": "4" }, { "SSID":"variable blaat5", "PASS":"variable Abc5", "NUMBER": "5" } ]}
实际错误结构
多次操作后得到的无效结构:
{ "information": {}, "test": [ "mooiman\n", "mooiweer\n" ], "number": [ 1, 2 ] }
测试代码
#include <Arduino.h> #include <WiFi.h> #include "FS.h" #include "SPIFFS.h" #include <ArduinoJson.h> int numberofInputs = 1; String ssid = "YourSSID"; String passwords = "YourPassword"; String readString; char FileReadBuff[1024]; DynamicJsonDocument doc(1024); void readFile(fs::FS &fs, const char * path){ if (SPIFFS.exists("/SSID.json") == false) { File file = SPIFFS.open("/SSID.json", FILE_WRITE); if (!file) { Serial.println("There was an error opening the file for writing"); return; } if (file.print("SSID")) { Serial.println("File was written"); } else { Serial.println("File write failed"); } file.close(); } Serial.printf("Reading file: %s\r\n", path); File file = fs.open(path); if(!file || file.isDirectory()){ Serial.println("- failed to open file for reading"); return; } uint16_t i = 0; Serial.println("reading"); while (file.available()) { FileReadBuff[i] = file.read(); i++; } file.close(); } void CleanFile(fs::FS &fs, const char * path, const char * message) { for( int i = 0; i < sizeof(FileReadBuff); ++i ){ FileReadBuff[i] = (char)0; } File file = SPIFFS.open(path, FILE_WRITE); if (fs.remove(path)) { Serial.println("\r\n- file cleaned"); } else { Serial.println("\r\n- Cleaning failed"); } file.print(path); } void appendFile(fs::FS &fs, const char * path, const char * message){ if (SPIFFS.exists("/SSID.json") == false) { File file = SPIFFS.open("/SSID.json", FILE_WRITE); if (!file) { Serial.println("There was an error opening the file for writing"); return; } if (file.print("SSID")) { Serial.println("File was written"); } else { Serial.println("File write failed"); } file.close(); } Serial.printf("Appending to file: %s\r\n", path); File file = fs.open(path, FILE_APPEND); if(!file){ Serial.println("- failed to open file for appending"); return; } if(file.println(message)){ Serial.println("- message appended"); } else { Serial.println("- append failed"); } file.close(); } void Deserialization(){ for( int i = 0; i < sizeof(FileReadBuff); ++i ){ FileReadBuff[i] = (char)0; } readFile(SPIFFS, "/SSID.json"); //read everything from ssid.json file const char * JsonFF = FileReadBuff; // put everything in to const char Serial.print("Json From File:"); Serial.println(JsonFF); DeserializationError error = deserializeJson(doc, JsonFF); if(error){ Serial.print(F("deserializeJson() failed: ")); Serial.println(error.f_str()); // if not legit print error } if(!error){ String information = doc["information"]; Serial.println(information); information = ""; } } void testjson(){ readString = ""; while(readString.length() < 1) { while (Serial.available()) { delay(10); //small delay to allow input buffer to fill if (Serial.available() > 0) { char c = Serial.read(); //gets one byte from serial buffer if (c == ',') { break; } //breaks out of capture loop to print readstring readString += c; } //makes the string readString } if (readString.length() > 0) { Serial.println(readString); //prints string to serial port out if (readString.indexOf("READ") >= 0) { Serial.println("reading file"); readFile(SPIFFS, "/SSID.json"); Serial.println(FileReadBuff); for( int i = 0; i < sizeof(FileReadBuff); ++i ){ FileReadBuff[i] = (char)0; } } if (readString.indexOf("DES") >= 0) { //DEZ deserialize will result in an error because json file is currently not valid Serial.println("reading deserialized json"); Deserialization(); } if (readString.indexOf("CLEAN") >= 0) { //CLEAN cleans the SSID.json file Serial.println("reading deserialized json"); CleanFile(SPIFFS, "/SSID.json", ""); } if (readString.indexOf("WRANDOM") >= 0){ //WRANDOM writes a random string to the SSID.json file readString = ""; Serial.println("Going to write the following input:"); //waiting for user input while(readString.length() < 1) { while (Serial.available()) { delay(10); //small delay to allow input buffer to fill if (Serial.available() > 0) { char c = Serial.read(); //gets one byte from serial buffer if (c == ',') { break; } //breaks out of capture loop to print readstring readString += c; } //makes the string readString } if (readString.length() > 0) { Serial.println(readString); //prints string to serial port out CleanFile(SPIFFS, "/SSID.json", ""); JsonObject information = doc.createNestedObject("information"); String SerializedJson = ""; doc["test"].add(readString); doc["number"].add(numberofInputs); serializeJsonPretty(doc, SerializedJson); appendFile(SPIFFS, "/SSID.json", SerializedJson.c_str()); SerializedJson = ""; numberofInputs ++; return; } } } } } } void setup() { Serial.begin(115200); if (!SPIFFS.begin(true)) { Serial.println("An Error has occurred while mounting SPIFFS"); return; } if (SPIFFS.exists("/SSID.json") == false) { File file = SPIFFS.open("/SSID.json", FILE_WRITE); if (!file) { Serial.println("There was an error opening the file for writing"); return; } if (file.print("SSID")) { Serial.println("File was written"); } else { Serial.println("File write failed"); } file.close(); } WiFi.mode(WIFI_MODE_STA); WiFi.begin(ssid.c_str(), passwords.c_str()); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } Serial.println("Connected"); } void loop() { readString = ""; Serial.println("Ready for new input: "); testjson(); }
操作流程
发送WRANDOM指令后输入内容,多次执行该操作,再发送READ指令查看/SSID.json文件,发现结构不符合预期。
备注:DynamicJsonDocument初始为空;暂不考虑LittleFS,优先解决当前SPIFFS的问题,也可考虑为每组SSID+密码创建单独文件。
解决方案
原代码核心问题
- 初始文件非法:首次创建文件时写入的是
"SSID"字符串,不是合法JSON,导致后续反序列化失败 - 结构逻辑错误:WRANDOM分支错误创建
information嵌套对象而非数组,且使用了test/number等无关键名 - 更新逻辑错误:没有读取现有JSON并追加新条目,而是清空后写入错误结构
- CleanFile函数逻辑混乱:删除文件后又打开写入路径字符串,导致文件内容无效
修正步骤
- 初始化合法空JSON:首次创建文件时写入
{"information":[]},确保后续反序列化正常 - 正确读取并更新JSON:每次新增条目时,先读取现有文件反序列化到
doc,获取information数组,添加新的SSID/PASS对象 - 覆盖写入完整JSON:更新完成后,直接覆盖写入整个JSON结构,避免追加导致的格式错误
- 修正CleanFile函数:清空文件内容为合法空JSON,而非删除后写入无效内容
完整修正代码
#include <Arduino.h> #include <WiFi.h> #include "FS.h" #include "SPIFFS.h" #include <ArduinoJson.h> int numberofInputs = 1; String ssid = "YourSSID"; String passwords = "YourPassword"; String readString; char FileReadBuff[1024]; DynamicJsonDocument doc(1024); void readFile(fs::FS &fs, const char * path){ // 初始化文件为合法空JSON if (!SPIFFS.exists(path)) { File file = fs.open(path, FILE_WRITE); if (!file) { Serial.println("Failed to open file for writing"); return; } if (file.print("{\"information\":[]}")) { Serial.println("Initial JSON file created"); } else { Serial.println("File write failed"); } file.close(); } Serial.printf("Reading file: %s\r\n", path); File file = fs.open(path); if(!file || file.isDirectory()){ Serial.println("- failed to open file for reading"); return; } uint16_t i = 0; memset(FileReadBuff, 0, sizeof(FileReadBuff)); // 先清空缓冲区 while (file.available() && i < sizeof(FileReadBuff)-1) { // 防止缓冲区溢出 FileReadBuff[i] = file.read(); i++; } file.close(); } void CleanFile(fs::FS &fs, const char * path) { File file = fs.open(path, FILE_WRITE); if(!file){ Serial.println("Failed to open file for cleaning"); return; } if(file.print("{\"information\":[]}")){ Serial.println("File cleaned"); } else { Serial.println("Clean failed"); } file.close(); memset(FileReadBuff, 0, sizeof(FileReadBuff)); numberofInputs = 1; // 重置计数 } void Deserialization(){ memset(FileReadBuff, 0, sizeof(FileReadBuff)); readFile(SPIFFS, "/SSID.json"); const char * JsonFF = FileReadBuff; Serial.print("Json From File:"); Serial.println(JsonFF); DeserializationError error = deserializeJson(doc, JsonFF); if(error){ Serial.print(F("deserializeJson() failed: ")); Serial.println(error.f_str()); return; } JsonArray infoArray = doc["information"].as<JsonArray>(); if(infoArray.isNull()){ Serial.println("information array not found"); return; } Serial.println("Deserialized entries:"); for(JsonObject entry : infoArray){ Serial.printf("NUMBER: %s, SSID: %s, PASS: %s\n", entry["NUMBER"].as<const char*>(), entry["SSID"].as<const char*>(), entry["PASS"].as<const char*>()); } } void testjson(){ readString = ""; while(readString.length() < 1) { while (Serial.available()) { delay(10); if (Serial.available() > 0) { char c = Serial.read(); if (c == '\n') { // 用换行结束指令输入 break; } readString += c; } } } readString.trim(); // 去掉首尾空白字符 if (readString.length() == 0) return; Serial.println("Received command: " + readString); if (readString.equals("READ")) { Serial.println("Reading file content:"); readFile(SPIFFS, "/SSID.json"); Serial.println(FileReadBuff); memset(FileReadBuff, 0, sizeof(FileReadBuff)); } else if (readString.equals("DES")) { Serial.println("Deserializing JSON:"); Deserialization(); } else if (readString.equals("CLEAN")) { Serial.println("Cleaning file:"); CleanFile(SPIFFS, "/SSID.json"); } else if (readString.equals("WRANDOM")) { readString = ""; Serial.println("Enter SSID,PASS (split by comma, press enter to confirm):"); while(readString.length() < 1) { while (Serial.available()) { delay(10); if (Serial.available() > 0) { char c = Serial.read(); if (c == '\n') { break; } readString += c; } } } readString.trim(); if (readString.length() == 0) return; Serial.println("Input received: " + readString); int commaIndex = readString.indexOf(','); if(commaIndex == -1){ Serial.println("Invalid format! Please use: SSID,PASS"); return; } String inputSSID = readString.substring(0, commaIndex); String inputPASS = readString.substring(commaIndex+1); inputSSID.trim(); inputPASS.trim(); // 读取现有JSON doc.clear(); readFile(SPIFFS, "/SSID.json"); DeserializationError error = deserializeJson(doc, FileReadBuff); if(error){ Serial.print("deserializeJson failed: "); Serial.println(error.f_str()); return; } // 获取或创建information数组 JsonArray infoArray = doc["information"].as<JsonArray>(); if(infoArray.isNull()){ infoArray = doc.createNestedArray("information"); } // 添加新条目 JsonObject newEntry = infoArray.createNestedObject(); newEntry["SSID"] = inputSSID; newEntry["PASS"] = inputPASS; newEntry["NUMBER"] = String(numberofInputs); // 覆盖写入文件 File file = SPIFFS.open("/SSID.json", FILE_WRITE); if(!file){ Serial.println("Failed to open file for writing"); return; } if(serializeJson(doc, file)){ Serial.println("New entry added successfully"); } else { Serial.println("Failed to write to file"); } file.close(); numberofInputs++; return; } else { Serial.println("Unknown command! Available commands: READ, DES, CLEAN, WRANDOM"); } } void setup() { Serial.begin(115200); if (!SPIFFS.begin(true)) { Serial.println("An Error has occurred while mounting SPIFFS"); return; } // 初始化SSID.json文件 if (!SPIFFS.exists("/SSID.json")) { File file = SPIFFS.open("/SSID.json", FILE_WRITE); if (!file) { Serial.println("Failed to open file for writing"); return;
相关产品推荐
相关产品推荐

