Closed noobGB closed 5 years ago
Hi @noobGB,
To update some fields of the JSON document, you must replace the values in the JsonDocument
and call serializeJson()
again.
Don't forget to clear the File
first; otherwise, the new JSON document will be appended to the old one.
Best Regards, Benoit
@noobGB,
As you replace values, watch out for values that are larger in size than the original. This is not an issue for fixed size objects like integers, but definitely is for char */strings.
e.g. if you have a string object "state" which could be "ON" or "OFF" and it's initial value is "ON" then
obj["state"] = "OFF";
will not generate an error, but obj["state"] will serialize back as "state": "null"
because ArduinoJson has no space in its document to fit the larger string. A shorter string will succeed (e.g. "OFF" as initial state turning to "ON").
To avoid this situation, cache the values for changing fields e.g. in item->state as in the following snippet:
if (strcmp(newstate, item->state)) { // state of type char* has changed
uint_fast16_t len = strlen(newstate) + 1;
item->state = (char *)realloc(item->state, len);
memcpy(item->state, newstate, len);
item->obj[F("state")] = (const char*)item->state;
}
SendJson(item->obj); // serialize item object as send back to client via webserver
In this example I don't serialize the whole JSON object back, but just one "item". If objects are larger, you might consider optimizing the traffic e.g. between client and (web)server... Regards, Ewald
Hi @bblanchon ,
Sorry I did not understand exactly, please check below code, if I call below function every time on any value update, would it be different from what you suggested or it would be a bad idea, please put some light into this,
void WriteConfigJson() {
//Serial.println("saving config");
const size_t capacity = JSON_OBJECT_SIZE(7)+400;
DynamicJsonDocument doc(capacity);
// store LEDstates and blynk token to the json object
doc["led1StateJson"] = led1State;
doc["led2StateJson"] = led2State;
doc["led3StateJson"] = led3State;
doc["blynk_tokenJson"] = blynk_tokenJson;
doc["server_idJson"] = server_id;
doc["Wifi_SSID_Json"] = ssid;
doc["Wifi_Pass_Json"] = password;
//ESP.wdtFeed(); // feed ESP for its internal processing or it will reboot
File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
//Serial.println("failed to open config file !!");
}
serializeJson(doc, configFile);
//delay(100);
//serializeJson(doc, Serial);
configFile.close();
}
Thank you!!
@noobGB, at first sight this looks OK if the variables led1State etc. are in scope (e.g. global variables) when executing the function
Yes @ewaldc, they are all global variables. Just for some clarification, what this function will do is, remove the existing json document( doc ) and create or serialize a new one every time ??
Since JSON document doc is local, it will be created, serialized and destroyed at each invocation.
What I meant with my earlier comment is that if you keep doc alive for longer periods of time and modify it as your led states change, something like
doc["led3StateJson"] = F("OFF");
will fail if doc["led3StateJson"] was less than 3 characters (e.g. "ON"). It will serialize as
"led3StateJson" : null
A typical example where such error could occur:
boolean led1State; // global variable
doc["led1State"] = (led1State) ? F("ON") : F("OFF");
However, with a global variable of type char* like in your example and _doc being recreated all the time, it's OK since ArduinoJson will simply store the pointer to your string, hence why it needs to stay in scope - in your example, until the json object is written to SPIFFS.
@noobGB, if you want to update one field in a file, you have to:
JsonDocument
(local, most likely)JsonDocument
to the fileDynamicJsonDocument doc(4096);
File file = SPIFFS.open("/config.json", "r");
deserializeJson(doc, file);
file.close();
doc["key"] = "value";
file = SPIFFS.open("/config.json", "w");
serializeJson(doc, file);
file.close();
BTW, there is a detailed case study of ArduinoJson with SPIFFS in Mastering ArduinoJson.
Hi @bblanchon ,
Thank you, I will try and get back to you here.
Hi @bblanchon ,
I have tried suggested code and it is working fine, thank you!!
Hi, I am using below code for serialization,
and below code for deserialization,
I want to update and store some(one or multiple) json fields whenever the field value changes in my program. @bblanchon ,Please help me with the update process or I should serialize the full json object every time.