Closed zibous closed 6 years ago
Hi @zibous,
If I understand correctly, you want to iterate through all the key-value pairs of a JsonObject
.
This can be done with a for loop on the JsonObject
, just like you did for the JsonArray
.
The trick is that the auto
is deduced to a JsonVariant
not a JsonObject
, so you need to cast.
Here, applied to the parseJSONdata()
from above:
void parseJSONdata(JsonArray &components) {
for (JsonObject &component : components) {
JsonArray &rows = component["rows"];
for (JsonObject &row : rows) {
for (JsonPair &column : row) {
Serial.println(column.key);
column.value = getUpdateValue(column.key);
}
}
}
}
See:
Hi bblanchon, Thanks for your information, works fine.
The json file is a template. After loading, I want to update the attributes with the device information. Therefore, I have to go through all nodes and check if something has changed. If so then these should be filled with the new value.
The only problem is that I can not update "column.value". Error: "operant types are ('Arduino :: JsonVariant and' String '").
String getUpdateValue(String fieldname, String defaultValue){
String cfgval;
// try to find the value
if (Embedis::get(fieldname, cfgval)) {
#ifdef DEBUG_MESSAGES
Serial.printf("[Field Update]\t Name:%s Value:%s\n", fieldname.c_str(), cfgval.c_str());
#endif
return cfgval;
}
#ifdef DEBUG_MESSAGES
Serial.printf("[Field Update]\t Name:%s not found !\n", fieldname.c_str());
#endif
return defaultValue;
}
void parseJSONdata(JsonArray &components){
for (JsonObject &component : components) {
JsonArray &rows = component["rows"];
for (JsonObject &row : rows) {
for (JsonPair &column : row) {
String fieldname = column.key;
if ( strcmp(column.key, "status")==0 ){
String _prefix = row["key"];
if(_prefix!="")
fieldname = _prefix + column.key;
}
column.value = getUpdateValue(fieldname, column.value);
}
}
}
}
FYI: PlatformIO Lib is 5.11.1, ArduinoJson 5.11.2 released 2 days ago is not aviable.
Indeed, this is a limitation of the current design of ArduinoJson.
A detached JsonVariant
is not able to make a copy of a String
.
There are two workarounds:
// 1. use the JsonBuffer directly.
column.value = jsonBuffer.strdup(getUpdateValue(fieldname, column.value));
// 2. pass through the JsonObject
row[column.key] = getUpdateValue(fieldname, column.value);
Sorry about that, this may change in 6.x.
Hi Benoît,
Thank you, works.
/**
* parse the json data of the template
* and update the values
*/
void parseJSONdata(JsonArray &components){
for (JsonObject &component : components) {
JsonArray &rows = component[F("rows")];
for (JsonObject &row : rows) {
if (row.containsKey(F("field")) && row.containsKey(F("value"))){
String fieldname = row[F("field")];
String newValue = getUpdateValue(fieldname);
if(newValue.length()){
#ifdef DEBUG_MESSAGES
Serial.printf("[Field Update]\t Update:%s=%s\n", fieldname.c_str(), newValue.c_str());
#endif
row[F("value")] = newValue;
}
}
}
}
}
New problem:
// try to open the json file
File file = SPIFFS.open(filename, "r");
if(file){
// file found, so we can prepare the data
DynamicJsonBuffer jsonBuffer;
// parse the file
JsonObject& data = jsonBuffer.parseObject(file);
// We don't need the file anymore
file.close();
if (!data.success()) {
#ifdef DEBUG_MESSAGES
Serial.printf("[WEBSERVER]\tError parsing file: %s\n", filename.c_str());
#endif
#ifdef SYSLOG_SUPPORT
syslog.logf(LOG_ERR, "Webserver Error open file: %s", filename.c_str());
#endif
sendAjaxMessage(F("error"), "System message", "Error parsing file " + filename);
return false;
}
...
}
For a larger Json file (> 3.5KB) this can not be parsed. The file is valid.
see: https://www.freeformatter.com/json-validator.html The JSON input is valid according to RFC 4627 (JSON specfication). The JSON input is valid in JavaScript.
PlatformIO: Can not upgrade to the latest version, ArduinoJson 5.11.2 is not (yet) available. PlatformIO Lib is 5.11.1, ArduinoJson 5.11.2 released 2 days ago is not aviable.
Hi @zibous,
It looks like a memory issue.
Try to pass the buffer size to the constructor of DynamicJsonBuffer
.
Use ArduinoJson Assistant to compute the size.
If it still doesn't work, it probably means that there is not enough RAM in the microcontroller.
Regards, Benoit
JsonObject has no member named key
Is there a simpler way to go through all the elements, but I did not find a solution. I am currently loading the data with "JsonObject& data = jsonBuffer.parseObject(file);" and then calling the parseJSONdata (data [F ("data")] function.
But get the error message:
Class ArduinoJson :: JsonObject has no member named key
json datafile