简体   繁体   中英

ArduinoJson parsing fail when reading string from EEPROM

Before someone flags this as duplicate I have found these two links and neither totally apply although I have implemented at least a little of both.

Buffer gets overwritten

Arduino reading json from EEPROM / converting uint8_t to char

My problem is this. I am trying to read and write a JSON string to an Arduinos EEPROM using ArduinoJson library ( https://github.com/bblanchon/ArduinoJson ). In the below code I generate a JsonObject from a hard coded JSON string (this works). I then write it to EEPROM (this works). It then gets read back from EEPROM (this works) but when I try and parse the second string using ArduinoJSON i get a parse failure.

For the purpose of testing I also clear the EEPROM each time just in case although eventually this will be removed.

The code compiles with no errors. I am hoping that someone more knowledgable in C++ than myself will spot something really obvious. I am compiling this onto a NodeMCU (esp8266).

#include <ArduinoJson.h>
#include <EEPROM.h>

StaticJsonBuffer<400> jsonBuffer;
JsonObject *jsonObject;
JsonObject *config;

String dummyJson = "{\"name\":\"RGB LED 1\",\"io\":[\"pwm1\",\"pwm2\",\"pwm3\"],\"io_type\":\"output\",\"device\":\"pwm_output\",\"uuid\":\"5a81f424aaf8d1e951ae78d270668337\",\"ip\":\"255.255.255.255\"}";

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

  Serial.println("\n\n");
  clearEEPROM();
  createDummyJsonObject();
  writeJsonToEEPROM();
  readJsonFromEEPROM();
}

void createDummyJsonObject()
{
  jsonObject = &jsonBuffer.parseObject(dummyJson);
  if (!jsonObject->success())
  {
    Serial.println("jsonBuffer.parseObject() failed");
    return;
  }
  else
  {
    Serial.println("JSON object generated from dummy string");
    jsonObject->prettyPrintTo(Serial);
    Serial.println("\n\n");
  }
}

void loop()
{
  // not used
}

void clearEEPROM()
{
  for (int i = 0; i < 512 + 1; i++)
  {
    EEPROM.write(i, 0);
  }
  EEPROM.commit();
}

void writeJsonToEEPROM()
{
  String jsonStr;
  jsonObject->printTo(jsonStr);

  for (int i = 0; i < jsonStr.length(); ++i)
  {
    EEPROM.write(i, jsonStr[i]);
  }

  EEPROM.write(jsonStr.length(), byte(0));
  EEPROM.commit();
}

void readJsonFromEEPROM()
{
  String jsonStr;

  for (int i = 0; i < 512; ++i)
  {
    char c = char(EEPROM.read(i));
    if (c != 0)
    {
      jsonStr += c;
      delay(1);
    }
    else
    {
      break;
    }
  }
  Serial.println(jsonStr);

  char charBuf[jsonStr.length()];
  jsonStr.toCharArray(charBuf, jsonStr.length());
  config = &jsonBuffer.parseObject(charBuf);

  if (!config->success())
  {
    Serial.println("jsonObject.parseObject() failed ");
    return;
  }
  else
  {
    // Never reaches this point! 
    Serial.println("\nJSON object generated from EEPROM data");
    config->prettyPrintTo(Serial);
    Serial.println("\n\n");
  }
}

The size allocated for charBuf should be jsonStr.length() + 1 because you need space for a string terminator. Therefore you should also add something like charBuf[jsonStr.length()] = '\\0'; to provide that string terminator:

int const jsonStringLengh = jsonStr.length();
char charBuf[jsonStringLengh + 1];
jsonStr.toCharArray(charBuf, jsonStringLengh);
charBuf[jsonStringLengh] = '\0';

Ok so this solved it. All I had to do was create a new StaticJsonBuffer for the second string parse. For anyone who is having a similar issue here's the working code.

    #include <ArduinoJson.h>
#include <EEPROM.h>

StaticJsonBuffer<512> jsonBuffer;
JsonObject *jsonObject;
JsonObject *config;

String dummyJson = "{\"name\":\"RGB LED 1\",\"io\":[\"pwm1\",\"pwm2\",\"pwm3\"],\"io_type\":\"output\",\"device\":\"pwm_output\",\"uuid\":\"5a81f424aaf8d1e951ae78d270668337\",\"ip\":\"255.255.255.255\"}";

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

  clearEEPROM();
  createDummyJsonObject();
  writeJsonToEEPROM();
  readJsonFromEEPROM();
}

void createDummyJsonObject()
{
  jsonObject = &jsonBuffer.parseObject(dummyJson);
  if (!jsonObject->success())
  {
    Serial.println("jsonBuffer.parseObject() failed");
    return;
  }
  else
  {
    Serial.println("JSON object generated from dummy string");
  }
}

void loop()
{
  // not used
}

void clearEEPROM()
{
  for (int i = 0; i < 512 + 1; i++)
  {
    EEPROM.write(i, 0);
  }
  EEPROM.commit();
}

void writeJsonToEEPROM()
{
  String jsonStr;
  jsonObject->printTo(jsonStr);
  for (int i = 0; i < jsonStr.length(); ++i)
  {
    EEPROM.write(i, jsonStr[i]);
  }
  EEPROM.write(jsonStr.length(), byte(0));
  EEPROM.commit();
}

void readJsonFromEEPROM()
{
  String jsonStr;
  for (int i = 0; i < 512; ++i)
  {
    char c = char(EEPROM.read(i));
    if (c != 0)
    {
      jsonStr += c;
      delay(1);
    }
    else
    {
      break;
    }
  }

  StaticJsonBuffer<512> jsonBuffer2;
  config = &jsonBuffer2.parseObject(jsonStr);
  if (!config->success())
  {
    Serial.println("jsonObject.parseObject() failed ");
    return;
  }
  else
  {
    Serial.println("\nJSON object generated from EEPROM data");
    config->prettyPrintTo(Serial);
    Serial.println("\n\n");
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM