1

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");
  }
}

2 Answers 2

1

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';
Sign up to request clarification or add additional context in comments.

3 Comments

Ahh ok thanks for that. I've added that but still no luck. Have I made the correct changes? char charBuf[jsonStr.length() + 1]; jsonStr.toCharArray(charBuf, jsonStr.length() + 1); charBuf[jsonStr.length()] = '\0';
The buffer needs one byte more which must be set to '\0'. The number of chars you feed into toCharArray() does not change. I have updated the response to make this more clear. And indeed, it is not possible to format comments to display code nicely.
Ahh ok I see. Thanks. I think I was getting confused with number of chars to copy and the array index at which to write to. I actually solved it by creating another StaticJsonBuffer (I can only assume they get cleared after use) but I've learnt something about strings and char arrays so thanks
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");
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.