Arduinojson: Help with deserialising data by passing data between functions.

Created on 12 Aug 2020  路  7Comments  路  Source: bblanchon/ArduinoJson

First off, thank you so much @bblanchon for the fantastic library. (Also for help with getting the debug tool working in another issue, its been invaluable!)

My question is on some code I had working, which has either appeared to have stopped or been some UB that has only recently became an issue.

An example below shows a short code snippet of what I am trying to achieve. I have a single function where I want to deserialise the data the one time, but have a group of functions that check for matching keys. In my case, home automation where each group of function is things like lights, relays, etc. Previously, I had deserialised each time, but I am working on optimising my solution and for a few weeks it worked okay until now, which is why I suspect it is UB and probably the JsonObject can not be passed around as a pointer like this.

main.cpp

void Template_Load(){

char buffer[] = "{\"test\":1,\"test2\"}";

  DynamicJsonDocument doc(1500);
  DeserializationError error = deserializeJson(doc, buffer);

  JsonObject obj2 = doc.as<JsonObject>();
  JsonObject* obj = &obj2;                                   // Not sure of this, again, it worked

  parsesub_CheckAll(obj);
}


void parsesub_CheckAll(JsonObject* obj){
  parsesub_Settings(obj); 
  parsesub_Other(obj); 
//others
}

void parsesub_Settings(JsonObject* _obj){
   // Create local dereferenced variable
  JsonObject obj = (*_obj);                         // This I am unsure about, it seemed to work until recently

  if(!obj["test1"].isNull()){                          // esp8266_exception_decoder stops here with read error (Exc. 28)
     //do stuff
  }
//5-30 commands...
}

void parsesub_Other(JsonObject* _obj){
   // Create local dereferenced variable
  JsonObject obj = (*_obj);                       // If this is wrong, and/or, I can access the object as a pointer directly, what would the operator be... 

  if(!obj["test2"].isNull()){ 
     //do stuff
  }
}

I have been trying my hardest to get this to work, but I believe I have ran into not understanding the underlying methods arduinojson uses, and am most likely trying to access a memory location which is no longer valid. Any pointers (no pun intended) on how to best approach this scenario would be appreciated. I will have probaby 5-20 sub functions like this, so finding a way to minimise ram usage would be ideal. Maybe I should be passing the document instead?

Programmed with VScode, esp8266, arduinojson v6.15.2, [email protected] core.

Many Thanks,
Michael

question

All 7 comments

Hello Michael

Benoit is doing a great job with this library and with his support. Your question here is obviously not an issue for the ArduinoJson library but a question about C++ and the usage of the library. I strongly assume you already bought and read the ArduinoJson eBook before asking for Benoit's valuable time. If not, please do so immediately.

Having said that, you have some flaws in the code you pasted. It does not even compile. Please look at the example here:

https://wandbox.org/permlink/0xnXjEiA3s45oqlQ

And read Benoit's Book! After reading this you would use references instead of pointers and understand the use of the different data types after deserialization.

Hi Michael,

@smuellener placed you on the right track, but you can get one step further.

Unlike JsonDocument, JsonObject has reference semantics: copying a JsonObject doesn't copy the associated data.
Therefore, you don't need to use a pointer or a reference; you can simply pass by value.

Also, when you don't need to modify the object, you can use a JsonObjectConst.

Here is my revision of @smuellener's example:
https://wandbox.org/permlink/TdsmoOydCltBOfnO

@smuellener, thank you very much for the kind words ;-)

Best regards,
Benoit

Hello guys,

Thank you very much to the both of you. @smuellener Thank you for taking the time to show me how I should be approaching the situation, I was obviously adding an extra step I did not need.

@bblanchon Thank for adding improvements to the code too. It has worked for everything except the JsonArray type. Unless I am misunderstanding this statement "Also, when you don't need to modify the object, you can use a JsonObjectConst."

https://wandbox.org/permlink/DInU9lsEhgfQTxuX

I tried using .as<JsonObject>() before equating it to JsonArray, but that did not help.

Best regards,
Michael

Hi again,

Nevermind, I found the const types and have got it building again. Many thanks again for the help.

Best wishes,
Michael

For the record, if obj is a JsonObjectConst, you cannot write:

JsonArray array = obj["test3"];
for(JsonVariant v : array)
   // ...

The build fails because you cannot extract a non-const reference from a const reference.
So, instead, you must write:

JsonArrayConst array = obj["test3"];
for(JsonVariantConst v : array)
   // ...

Yes, that is what I concluded from the documents :)

My last question which I am now stuck on without the pointers, is there anyway to save the JsonObject as a global value? I have a "Tasker" function which goes around and polls different classes to execute commands, but currently I can't pass JsonObject into them as I have probably over 500 function calls (with templates) that I would need to fix before passing JsonObject directly. Previously, I assumed I could use JsonObject as a pointer and store/access it that way. Is there any true way to access the JsonObject globally in the interim. The functions which will be called will be within the function which deserialised the data, I won't be trying to access that "global copy" at any other time.

Thanks again

You can put the JsonDocument in the global scope, but you must be aware of the memory leak that it can produce.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

loewekordel picture loewekordel  路  4Comments

timpur picture timpur  路  5Comments

sorokolokarim picture sorokolokarim  路  5Comments

koffienl picture koffienl  路  3Comments

bepursuant picture bepursuant  路  4Comments