Json parsing not working with JsonObject using ArduinoJson library

1.2k views Asked by At

I am using the following code to store Config.json file to ESP32 flash memory using SPIFFS

#include <ArduinoJson.h>
#include <FS.h>
#include<SPIFFS.h>

bool loadConfig() {
File configFile = SPIFFS.open("/Config.json", "r");
if (!configFile) {
Serial.println("Failed to open config file");
return false;
}


size_t size = configFile.size();
if (size > 1024) {
Serial.println("Config file size is too large");
return false;
}


// Allocate a buffer to store contents of the file.

std::unique_ptr<char[]> buf(new char[size]);

// We don't use String here because ArduinoJson library requires the input
// buffer to be mutable. If you don't use ArduinoJson, you may as well
// use configFile.readString instead.


configFile.readBytes(buf.get(), size);
Serial.println(buf.get());


StaticJsonBuffer<1024> jsonBuffer;
JsonObject& json = jsonBuffer.parseObject(buf.get());


if (!json.success()) {
Serial.println("Failed to parse config file");
return false;
}

const char* ssid = json["ssid"];
const char* password = json["password"];

// Real world application would store these values in some variables for
// later use.


Serial.print("Loaded ssid: ");
Serial.println(ssid);
Serial.print("Loaded password: ");
Serial.println(password);
return true;
}


void setup() {
Serial.begin(115200);
Serial.println("");
delay(1000);
Serial.println("Mounting FS...");
if (!SPIFFS.begin()) {
Serial.println("Failed to mount file system");
return;
}




if (!loadConfig()) {
  
Serial.println("Failed to load config");

} 

else {
Serial.println("Config loaded");
}

}

void loop() {
yield();

}

However the parsing fails, and I get the following message on the serial monitor: Mounting FS... ⸮xV⸮⸮⸮⸮⸮ Failed to parse config file Failed to load config

  • My Arduino IDE version: 1.8.13 (Windows)
  • Config file has 2 objects:
    {
        "ssid": "ESP32",
        "password": "Softronics"    
      }

Thank you in advance

2

There are 2 answers

3
romkey On BEST ANSWER

There's no need to pre-allocate a buffer to store the file for ArduinoJSON. ArduinoJSON is quite capable of reading the file itself and avoiding the need to manage a buffer for the file.

This code is unnecessary. You should not allocate a buffer.

std::unique_ptr<char[]> buf(new char[size]);

// We don't use String here because ArduinoJson library requires the input
// buffer to be mutable. If you don't use ArduinoJson, you may as well
// use configFile.readString instead.


configFile.readBytes(buf.get(), size);
Serial.println(buf.get());


StaticJsonBuffer<1024> jsonBuffer;
JsonObject& json = jsonBuffer.parseObject(buf.get());

if (!json.success()) {
Serial.println("Failed to parse config file");
return false;
}

Here's a complete program which works correctly for me:

#include <ArduinoJson.h>
#include <FS.h>
#include<SPIFFS.h>

bool loadConfig() {
  File configFile = SPIFFS.open("/Config.json", "r");
  if (!configFile) {
    Serial.println("Failed to open config file");
    return false;
  }


  size_t size = configFile.size();
  if (size > 1024) {
    Serial.println("Config file size is too large");
    return false;
  }

  StaticJsonDocument<1024> doc;
  DeserializationError error = deserializeJson(doc, configFile);

  if(error) {
    Serial.println("Failed to parse config file");
    return false;
  }

  const char* ssid = doc["ssid"];
  const char* password = doc["password"];

  // Real world application would store these values in some variables for
  // later use.


  Serial.print("Loaded ssid: ");
  Serial.println(ssid);
  Serial.print("Loaded password: ");
  Serial.println(password);
  return true;
}


void setup() {
  Serial.begin(115200);
  Serial.println("");
  delay(1000);
  Serial.println("Mounting FS...");
  if (!SPIFFS.begin()) {
    Serial.println("Failed to mount file system");
    return;
  }

  if (!loadConfig()) {
    Serial.println("Failed to load config");
  } 
  else {
    Serial.println("Config loaded");
  }
}

void loop() {
  yield();

}

The code you posted was for ArduinoJSON version 5, which is obsolete. This uses ArduinoJSON version 6. You should upgrade your library to use it.

The ArduinoJSON documentation and examples are quite helpful when writing code that uses the library.

Also, please try indenting your code, at least as a courtesy to others if not to do yourself a favor. Proper indentation makes code much more readable.

0
Miguel Tomás On

To parse an ArduinoJSON one simply needs to

  String JSONpayload = "some JSON here";
  StaticJsonDocument <512> geoLocationInfoJson;
  DeserializationError error = deserializeJson(geoLocationInfoJson, JSONpayload);
  if (error) {
    this->mserial->printStrln("Error deserializing JSON");
  }

To use the values within the StaticJsonDocument one first needs to

if ( geoLocationInfoJson.isNull() == true ){
  String dataStr="NULL geoLocation data.\n";
  Serial.print( dataStr); 
  return true;
}

next, is required to verify if a key exists. If TRUE, then is mandatory first to get the desired value into a corresponding data type, like below, and only afterward work on it, for instance, send it as a BLE message string:

if(this->interface->geoLocationInfoJson.containsKey("lat")){
  float lat = this->interface->geoLocationInfoJson["lat"];
  dataStr += "Latitude: "+ String(lat,4) + "\n";
}
if(this->interface->geoLocationInfoJson.containsKey("lon")){
  float lon = this->interface->geoLocationInfoJson["lon"];
  dataStr += "Longitude: "+ String(lon,4) + "\n";
}

if(this->interface->geoLocationInfoJson.containsKey("regionName"))
  dataStr += String(this->interface->geoLocationInfoJson["regionName"].as<char*>()) + ", ";