Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial serializing #2079

Closed
hitecSmartHome opened this issue Apr 15, 2024 · 7 comments
Closed

Initial serializing #2079

hitecSmartHome opened this issue Apr 15, 2024 · 7 comments
Labels
question v7 ArduinoJson 7

Comments

@hitecSmartHome
Copy link

Hello I need some help!

I'm using Arduino as an IDF component.
My device is an ESP32-Wrover-E ( 16mb ram and 4mb psram )
I'm using ArduinoJson V7.

I have a global char array which is allocated from External ram. This char array is used for syncronisation purposes across my code.
It contains fresh information about components.

Here is my function which I have problem with.

boolean ComponentHandler::updateZones(JsonObject newZoneData){
    JsonDocument zonesObj;
    DeserializationError error = deserializeJson(zonesObj, (const char*)zones);
    if(error){ zonesObj.clear(); } // I have tried to just ignore the error

    std::string id = newZoneData["id"];
    if( zonesObj[id].isNull() ){
        JsonObject zone = zonesObj[id].to<JsonObject>();
        zone.set( newZoneData );
    }else{
        zonesObj[id].set( newZoneData );
    }
    return serializeJson(zonesObj, zones, ZONES_SIZE) > 0;
}

The thing is that initially the zones char array is empty. So the deserializeJson will fail.
The zones object looks something like this:

{
 "restzthhgf":{
     "thing1":5
  },
 "dgfcvtrtrh":{
     "thing1":5
  }
}

When the zones char array is empty sometimes I get 2 from the serializeJson which is bigger than 0 so the function will return true.

I'm allocating ram for it like this

if( !hshSystem.alloc(zones,ZONES_SIZE) ){
    printf("FAILED TO ALLOCATE ZONES ARRAY\n");
}

alloc method is just a wrapper for ps_malloc

boolean Sys::alloc(char *&ptr, int size) {
    ptr = (char *)ps_malloc(size * sizeof(char));
    if (!ptr || ptr == NULL) {
        return false;
    }
    return true;
}

So the idea of this function is that it tries to deserialize the zones array first so I can have an object representation of the global zones.
After that it checks if a zone with the given id exists. If it exists, it will overwrite, if it does not exists it creates it.
But when serialization happens, i got 2 as the output.

@bblanchon
Copy link
Owner

Hi @hitecSmartHome,

It looks like you can simplify your code like so:

  boolean ComponentHandler::updateZones(JsonObject newZoneData){
      JsonDocument zonesObj;
      DeserializationError error = deserializeJson(zonesObj, (const char*)zones);
      if(error){ zonesObj.clear(); } // I have tried to just ignore the error
  
-     std::string id = newZoneData["id"];
-     if( zonesObj[id].isNull() ){
-         JsonObject zone = zonesObj[id].to<JsonObject>();
-         zone.set( newZoneData );
-     }else{
-         zonesObj[id].set( newZoneData );
-     }
+     zonesObj[newZoneData["id"]] = newZoneData;
      return serializeJson(zonesObj, zones, ZONES_SIZE) > 0;
  }

But what is your question exactly?

Best regards,
Benoit

@bblanchon bblanchon added the v7 ArduinoJson 7 label Apr 16, 2024
@hitecSmartHome
Copy link
Author

Thanks for the suggestion.

The question is that if I serialize it why do i get string "2" instead of a string object.

@hitecSmartHome
Copy link
Author

It doesn't work like that

boolean ComponentHandler::updateZones(JsonObject newZoneData){
    JsonDocument zonesObj;
    deserializeJson(zonesObj, (const char*)zones); // Doesn't matter if the zones char array is empty or not.
    zonesObj[newZoneData["id"]] = newZoneData; // Does not save it. I have to use set() method
    return serializeJson(zonesObj, zones, ZONES_SIZE) > 0;
}

@bblanchon
Copy link
Owner

Indeed, I just realized that doc[var] doesn't work when var is a string; it only works with integers.
This is clearly a bug.
Until I fix it, please use zonesObj[newZoneData["id"].as<JsonString>()] = newZoneData; instead.

About your original issue, where serializeJson() produces 2 as the output JSON document, this could be due to the initial data in the zones buffer.
Please add a terminator at the beginning of the buffer to ensure that deserializeJson() sees an empty input.

  if( !hshSystem.alloc(zones,ZONES_SIZE) ){
      printf("FAILED TO ALLOCATE ZONES ARRAY\n");
+     return;
  }
+ zones[0] = 0;

@hitecSmartHome
Copy link
Author

I see. Will check it, thank you very much! And I will try with JsonString also.

@hitecSmartHome
Copy link
Author

hitecSmartHome commented Apr 18, 2024

Confirmed it is working with JsonString.

boolean ComponentHandler::updateZones(JsonObject newZoneData){
    JsonDocument zonesObj;
    deserializeJson(zonesObj, (const char*)zones);
    zonesObj[newZoneData["id"].as<JsonString>()] = newZoneData;
    return serializeJson(zonesObj, zones, ZONES_SIZE) > 0;
}

Thank you very much. Will test this

if( !hshSystem.alloc(zones,ZONES_SIZE) ){
      printf("FAILED TO ALLOCATE ZONES ARRAY\n");
+     return;
  }
+ zones[0] = 0;

@hitecSmartHome
Copy link
Author

It works fine. Thank you very much for the help. I appreciate it.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 24, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
question v7 ArduinoJson 7
Projects
None yet
Development

No branches or pull requests

2 participants